1
0
forked from ruoyi/RuoYi-Vue

优化代码,支持防盗链功能

This commit is contained in:
2025-09-20 21:19:02 +08:00
parent 616e257617
commit 1b140fcc83
8 changed files with 530 additions and 481 deletions

View File

@@ -127,6 +127,13 @@ springdoc:
paths-to-match: '/**' paths-to-match: '/**'
packages-to-scan: com.devttl.web.controller.tool packages-to-scan: com.devttl.web.controller.tool
# 防盗链配置
referer:
# 防盗链开关
enabled: false
# 允许的域名列表
allowed-domains: localhost,127.0.0.1,devttl.com,www.devttl.com
# 防止XSS攻击 # 防止XSS攻击
xss: xss:
# 过滤开关 # 过滤开关

View File

@@ -0,0 +1,63 @@
package com.devttl.common.filter;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* 防盗链过滤器
*
* @author ruoyi
*/
public class RefererFilter implements Filter {
/**
* 允许的域名列表
*/
public List<String> allowedDomains;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String domains = filterConfig.getInitParameter("allowedDomains");
this.allowedDomains = Arrays.asList(domains.split(","));
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String referer = req.getHeader("Referer");
// 如果Referer为空拒绝访问
if (referer == null || referer.isEmpty()) {
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
return;
}
// 检查Referer是否在允许的域名列表中
boolean allowed = false;
for (String domain : allowedDomains) {
if (referer.contains(domain)) {
allowed = true;
break;
}
}
// 根据检查结果决定是否放行
if (allowed) {
chain.doFilter(request, response);
} else {
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
}
}
@Override
public void destroy() {
}
}

View File

@@ -1,16 +1,19 @@
package com.devttl.framework.config; package com.devttl.framework.config;
import java.util.HashMap; import com.devttl.common.constant.Constants;
import java.util.Map; import com.devttl.common.filter.RefererFilter;
import com.devttl.common.filter.RepeatableFilter;
import com.devttl.common.filter.XssFilter;
import com.devttl.common.utils.StringUtils;
import jakarta.servlet.DispatcherType; import jakarta.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import com.devttl.common.filter.RepeatableFilter;
import com.devttl.common.filter.XssFilter; import java.util.HashMap;
import com.devttl.common.utils.StringUtils; import java.util.Map;
/** /**
* Filter配置 * Filter配置
@@ -18,19 +21,20 @@ import com.devttl.common.utils.StringUtils;
* @author devttl * @author devttl
*/ */
@Configuration @Configuration
public class FilterConfig public class FilterConfig {
{
@Value("${xss.excludes}") @Value("${xss.excludes}")
private String excludes; private String excludes;
@Value("${xss.urlPatterns}") @Value("${xss.urlPatterns}")
private String urlPatterns; private String urlPatterns;
@Value("${referer.allowed-domains}")
private String allowedDomains;
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@Bean @Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true") @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean xssFilterRegistration() public FilterRegistrationBean xssFilterRegistration() {
{
FilterRegistrationBean registration = new FilterRegistrationBean(); FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter()); registration.setFilter(new XssFilter());
@@ -45,8 +49,23 @@ public class FilterConfig
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@Bean @Bean
public FilterRegistrationBean someFilterRegistration() @ConditionalOnProperty(value = "referer.enabled", havingValue = "true")
{ public FilterRegistrationBean refererFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new RefererFilter());
registration.addUrlPatterns(Constants.RESOURCE_PREFIX + "/*");
registration.setName("refererFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("allowedDomains", allowedDomains);
registration.setInitParameters(initParameters);
return registration;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean someFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(); FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatableFilter()); registration.setFilter(new RepeatableFilter());
registration.addUrlPatterns("/*"); registration.addUrlPatterns("/*");

View File

@@ -1,24 +1,12 @@
package com.devttl.framework.web.service; package com.devttl.framework.web.service;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.devttl.common.constant.CacheConstants; import com.devttl.common.constant.CacheConstants;
import com.devttl.common.constant.Constants; import com.devttl.common.constant.Constants;
import com.devttl.common.constant.UserConstants; import com.devttl.common.constant.UserConstants;
import com.devttl.common.core.domain.entity.SysUser;
import com.devttl.common.core.domain.model.LoginUser; import com.devttl.common.core.domain.model.LoginUser;
import com.devttl.common.core.redis.RedisCache; import com.devttl.common.core.redis.RedisCache;
import com.devttl.common.exception.ServiceException; import com.devttl.common.exception.ServiceException;
import com.devttl.common.exception.user.BlackListException; import com.devttl.common.exception.user.*;
import com.devttl.common.exception.user.CaptchaException;
import com.devttl.common.exception.user.CaptchaExpireException;
import com.devttl.common.exception.user.UserNotExistsException;
import com.devttl.common.exception.user.UserPasswordNotMatchException;
import com.devttl.common.utils.DateUtils; import com.devttl.common.utils.DateUtils;
import com.devttl.common.utils.MessageUtils; import com.devttl.common.utils.MessageUtils;
import com.devttl.common.utils.StringUtils; import com.devttl.common.utils.StringUtils;
@@ -28,6 +16,14 @@ import com.devttl.framework.manager.factory.AsyncFactory;
import com.devttl.framework.security.context.AuthenticationContextHolder; import com.devttl.framework.security.context.AuthenticationContextHolder;
import com.devttl.system.service.ISysConfigService; import com.devttl.system.service.ISysConfigService;
import com.devttl.system.service.ISysUserService; import com.devttl.system.service.ISysUserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/** /**
* 登录校验方法 * 登录校验方法
@@ -35,8 +31,7 @@ import com.devttl.system.service.ISysUserService;
* @author devttl * @author devttl
*/ */
@Component @Component
public class SysLoginService public class SysLoginService {
{
@Autowired @Autowired
private TokenService tokenService; private TokenService tokenService;
@@ -61,36 +56,27 @@ public class SysLoginService
* @param uuid 唯一标识 * @param uuid 唯一标识
* @return 结果 * @return 结果
*/ */
public String login(String username, String password, String code, String uuid) public String login(String username, String password, String code, String uuid) {
{
// 验证码校验 // 验证码校验
validateCaptcha(username, code, uuid); validateCaptcha(username, code, uuid);
// 登录前置校验 // 登录前置校验
loginPreCheck(username, password); loginPreCheck(username, password);
// 用户验证 // 用户验证
Authentication authentication = null; Authentication authentication = null;
try try {
{
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationContextHolder.setContext(authenticationToken); AuthenticationContextHolder.setContext(authenticationToken);
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager.authenticate(authenticationToken); authentication = authenticationManager.authenticate(authenticationToken);
} } catch (Exception e) {
catch (Exception e) if (e instanceof BadCredentialsException) {
{
if (e instanceof BadCredentialsException)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException(); throw new UserPasswordNotMatchException();
} } else {
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
throw new ServiceException(e.getMessage()); throw new ServiceException(e.getMessage());
} }
} } finally {
finally
{
AuthenticationContextHolder.clearContext(); AuthenticationContextHolder.clearContext();
} }
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
@@ -108,21 +94,17 @@ public class SysLoginService
* @param uuid 唯一标识 * @param uuid 唯一标识
* @return 结果 * @return 结果
*/ */
public void validateCaptcha(String username, String code, String uuid) public void validateCaptcha(String username, String code, String uuid) {
{
boolean captchaEnabled = configService.selectCaptchaEnabled(); boolean captchaEnabled = configService.selectCaptchaEnabled();
if (captchaEnabled) if (captchaEnabled) {
{
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
String captcha = redisCache.getCacheObject(verifyKey); String captcha = redisCache.getCacheObject(verifyKey);
if (captcha == null) if (captcha == null) {
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException(); throw new CaptchaExpireException();
} }
redisCache.deleteObject(verifyKey); redisCache.deleteObject(verifyKey);
if (!code.equalsIgnoreCase(captcha)) if (!code.equalsIgnoreCase(captcha)) {
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException(); throw new CaptchaException();
} }
@@ -131,35 +113,31 @@ public class SysLoginService
/** /**
* 登录前置校验 * 登录前置校验
*
* @param username 用户名 * @param username 用户名
* @param password 用户密码 * @param password 用户密码
*/ */
public void loginPreCheck(String username, String password) public void loginPreCheck(String username, String password) {
{
// 用户名或密码为空 错误 // 用户名或密码为空 错误
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
throw new UserNotExistsException(); throw new UserNotExistsException();
} }
// 密码如果不在指定范围内 错误 // 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException(); throw new UserPasswordNotMatchException();
} }
// 用户名不在指定范围内 错误 // 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException(); throw new UserPasswordNotMatchException();
} }
// IP黑名单校验 // IP黑名单校验
String blackStr = configService.selectConfigByKey("sys.login.blackIPList"); String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
throw new BlackListException(); throw new BlackListException();
} }
@@ -170,12 +148,7 @@ public class SysLoginService
* *
* @param userId 用户ID * @param userId 用户ID
*/ */
public void recordLoginInfo(Long userId) public void recordLoginInfo(Long userId) {
{ userService.updateLoginInfo(userId, IpUtils.getIpAddr(), DateUtils.getNowDate());
SysUser sysUser = new SysUser();
sysUser.setUserId(userId);
sysUser.setLoginIp(IpUtils.getIpAddr());
sysUser.setLoginDate(DateUtils.getNowDate());
userService.updateUserProfile(sysUser);
} }
} }

View File

@@ -1,16 +1,17 @@
package com.devttl.system.mapper; package com.devttl.system.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.devttl.common.core.domain.entity.SysUser; import com.devttl.common.core.domain.entity.SysUser;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/** /**
* 用户表 数据层 * 用户表 数据层
* *
* @author devttl * @author devttl
*/ */
public interface SysUserMapper public interface SysUserMapper {
{
/** /**
* 根据条件分页查询用户列表 * 根据条件分页查询用户列表
* *
@@ -76,6 +77,16 @@ public interface SysUserMapper
*/ */
public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar); public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar);
/**
* 更新用户登录信息IP和登录时间
*
* @param userId 用户ID
* @param loginIp 登录IP地址
* @param loginDate 登录时间
* @return 结果
*/
public int updateLoginInfo(@Param("userId") Long userId, @Param("loginIp") String loginIp, @Param("loginDate") Date loginDate);
/** /**
* 重置用户密码 * 重置用户密码
* *

View File

@@ -1,15 +1,16 @@
package com.devttl.system.service; package com.devttl.system.service;
import java.util.List;
import com.devttl.common.core.domain.entity.SysUser; import com.devttl.common.core.domain.entity.SysUser;
import java.util.Date;
import java.util.List;
/** /**
* 用户 业务层 * 用户 业务层
* *
* @author devttl * @author devttl
*/ */
public interface ISysUserService public interface ISysUserService {
{
/** /**
* 根据条件分页查询用户列表 * 根据条件分页查询用户列表
* *
@@ -161,6 +162,16 @@ public interface ISysUserService
*/ */
public boolean updateUserAvatar(Long userId, String avatar); public boolean updateUserAvatar(Long userId, String avatar);
/**
* 更新用户登录信息IP和登录时间
*
* @param userId 用户ID
* @param loginIp 登录IP地址
* @param loginDate 登录时间
* @return 结果
*/
public void updateLoginInfo(Long userId, String loginIp, Date loginDate);
/** /**
* 重置用户密码 * 重置用户密码
* *

View File

@@ -1,15 +1,5 @@
package com.devttl.system.service.impl; package com.devttl.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import jakarta.validation.Validator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.devttl.common.annotation.DataScope; import com.devttl.common.annotation.DataScope;
import com.devttl.common.constant.UserConstants; import com.devttl.common.constant.UserConstants;
import com.devttl.common.core.domain.entity.SysRole; import com.devttl.common.core.domain.entity.SysRole;
@@ -22,14 +12,22 @@ import com.devttl.common.utils.spring.SpringUtils;
import com.devttl.system.domain.SysPost; import com.devttl.system.domain.SysPost;
import com.devttl.system.domain.SysUserPost; import com.devttl.system.domain.SysUserPost;
import com.devttl.system.domain.SysUserRole; import com.devttl.system.domain.SysUserRole;
import com.devttl.system.mapper.SysPostMapper; import com.devttl.system.mapper.*;
import com.devttl.system.mapper.SysRoleMapper;
import com.devttl.system.mapper.SysUserMapper;
import com.devttl.system.mapper.SysUserPostMapper;
import com.devttl.system.mapper.SysUserRoleMapper;
import com.devttl.system.service.ISysConfigService; import com.devttl.system.service.ISysConfigService;
import com.devttl.system.service.ISysDeptService; import com.devttl.system.service.ISysDeptService;
import com.devttl.system.service.ISysUserService; import com.devttl.system.service.ISysUserService;
import jakarta.validation.Validator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/** /**
* 用户 业务层处理 * 用户 业务层处理
@@ -37,8 +35,7 @@ import com.devttl.system.service.ISysUserService;
* @author devttl * @author devttl
*/ */
@Service @Service
public class SysUserServiceImpl implements ISysUserService public class SysUserServiceImpl implements ISysUserService {
{
private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
@Autowired @Autowired
@@ -73,8 +70,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u") @DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectUserList(SysUser user) public List<SysUser> selectUserList(SysUser user) {
{
return userMapper.selectUserList(user); return userMapper.selectUserList(user);
} }
@@ -86,8 +82,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u") @DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectAllocatedList(SysUser user) public List<SysUser> selectAllocatedList(SysUser user) {
{
return userMapper.selectAllocatedList(user); return userMapper.selectAllocatedList(user);
} }
@@ -99,8 +94,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u") @DataScope(deptAlias = "d", userAlias = "u")
public List<SysUser> selectUnallocatedList(SysUser user) public List<SysUser> selectUnallocatedList(SysUser user) {
{
return userMapper.selectUnallocatedList(user); return userMapper.selectUnallocatedList(user);
} }
@@ -111,8 +105,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 用户对象信息 * @return 用户对象信息
*/ */
@Override @Override
public SysUser selectUserByUserName(String userName) public SysUser selectUserByUserName(String userName) {
{
return userMapper.selectUserByUserName(userName); return userMapper.selectUserByUserName(userName);
} }
@@ -123,8 +116,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 用户对象信息 * @return 用户对象信息
*/ */
@Override @Override
public SysUser selectUserById(Long userId) public SysUser selectUserById(Long userId) {
{
return userMapper.selectUserById(userId); return userMapper.selectUserById(userId);
} }
@@ -135,11 +127,9 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public String selectUserRoleGroup(String userName) public String selectUserRoleGroup(String userName) {
{
List<SysRole> list = roleMapper.selectRolesByUserName(userName); List<SysRole> list = roleMapper.selectRolesByUserName(userName);
if (CollectionUtils.isEmpty(list)) if (CollectionUtils.isEmpty(list)) {
{
return StringUtils.EMPTY; return StringUtils.EMPTY;
} }
return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
@@ -152,11 +142,9 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public String selectUserPostGroup(String userName) public String selectUserPostGroup(String userName) {
{
List<SysPost> list = postMapper.selectPostsByUserName(userName); List<SysPost> list = postMapper.selectPostsByUserName(userName);
if (CollectionUtils.isEmpty(list)) if (CollectionUtils.isEmpty(list)) {
{
return StringUtils.EMPTY; return StringUtils.EMPTY;
} }
return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
@@ -169,12 +157,10 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public boolean checkUserNameUnique(SysUser user) public boolean checkUserNameUnique(SysUser user) {
{
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
SysUser info = userMapper.checkUserNameUnique(user.getUserName()); SysUser info = userMapper.checkUserNameUnique(user.getUserName());
if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
{
return UserConstants.NOT_UNIQUE; return UserConstants.NOT_UNIQUE;
} }
return UserConstants.UNIQUE; return UserConstants.UNIQUE;
@@ -187,12 +173,10 @@ public class SysUserServiceImpl implements ISysUserService
* @return * @return
*/ */
@Override @Override
public boolean checkPhoneUnique(SysUser user) public boolean checkPhoneUnique(SysUser user) {
{
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
{
return UserConstants.NOT_UNIQUE; return UserConstants.NOT_UNIQUE;
} }
return UserConstants.UNIQUE; return UserConstants.UNIQUE;
@@ -205,12 +189,10 @@ public class SysUserServiceImpl implements ISysUserService
* @return * @return
*/ */
@Override @Override
public boolean checkEmailUnique(SysUser user) public boolean checkEmailUnique(SysUser user) {
{
Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
SysUser info = userMapper.checkEmailUnique(user.getEmail()); SysUser info = userMapper.checkEmailUnique(user.getEmail());
if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
{
return UserConstants.NOT_UNIQUE; return UserConstants.NOT_UNIQUE;
} }
return UserConstants.UNIQUE; return UserConstants.UNIQUE;
@@ -222,10 +204,8 @@ public class SysUserServiceImpl implements ISysUserService
* @param user 用户信息 * @param user 用户信息
*/ */
@Override @Override
public void checkUserAllowed(SysUser user) public void checkUserAllowed(SysUser user) {
{ if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) {
if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
{
throw new ServiceException("不允许操作超级管理员用户"); throw new ServiceException("不允许操作超级管理员用户");
} }
} }
@@ -236,15 +216,12 @@ public class SysUserServiceImpl implements ISysUserService
* @param userId 用户id * @param userId 用户id
*/ */
@Override @Override
public void checkUserDataScope(Long userId) public void checkUserDataScope(Long userId) {
{ if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
if (!SysUser.isAdmin(SecurityUtils.getUserId()))
{
SysUser user = new SysUser(); SysUser user = new SysUser();
user.setUserId(userId); user.setUserId(userId);
List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user); List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
if (StringUtils.isEmpty(users)) if (StringUtils.isEmpty(users)) {
{
throw new ServiceException("没有权限访问用户数据!"); throw new ServiceException("没有权限访问用户数据!");
} }
} }
@@ -258,8 +235,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@Transactional @Transactional
public int insertUser(SysUser user) public int insertUser(SysUser user) {
{
// 新增用户信息 // 新增用户信息
int rows = userMapper.insertUser(user); int rows = userMapper.insertUser(user);
// 新增用户岗位关联 // 新增用户岗位关联
@@ -276,8 +252,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public boolean registerUser(SysUser user) public boolean registerUser(SysUser user) {
{
return userMapper.insertUser(user) > 0; return userMapper.insertUser(user) > 0;
} }
@@ -289,8 +264,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@Transactional @Transactional
public int updateUser(SysUser user) public int updateUser(SysUser user) {
{
Long userId = user.getUserId(); Long userId = user.getUserId();
// 删除用户与角色关联 // 删除用户与角色关联
userRoleMapper.deleteUserRoleByUserId(userId); userRoleMapper.deleteUserRoleByUserId(userId);
@@ -311,8 +285,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@Transactional @Transactional
public void insertUserAuth(Long userId, Long[] roleIds) public void insertUserAuth(Long userId, Long[] roleIds) {
{
userRoleMapper.deleteUserRoleByUserId(userId); userRoleMapper.deleteUserRoleByUserId(userId);
insertUserRole(userId, roleIds); insertUserRole(userId, roleIds);
} }
@@ -324,8 +297,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int updateUserStatus(SysUser user) public int updateUserStatus(SysUser user) {
{
return userMapper.updateUser(user); return userMapper.updateUser(user);
} }
@@ -336,8 +308,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int updateUserProfile(SysUser user) public int updateUserProfile(SysUser user) {
{
return userMapper.updateUser(user); return userMapper.updateUser(user);
} }
@@ -349,11 +320,22 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public boolean updateUserAvatar(Long userId, String avatar) public boolean updateUserAvatar(Long userId, String avatar) {
{
return userMapper.updateUserAvatar(userId, avatar) > 0; return userMapper.updateUserAvatar(userId, avatar) > 0;
} }
/**
* 更新用户登录信息IP和登录时间
*
* @param userId 用户ID
* @param loginIp 登录IP地址
* @param loginDate 登录时间
* @return 结果
*/
public void updateLoginInfo(Long userId, String loginIp, Date loginDate) {
userMapper.updateLoginInfo(userId, loginIp, loginDate);
}
/** /**
* 重置用户密码 * 重置用户密码
* *
@@ -361,8 +343,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int resetPwd(SysUser user) public int resetPwd(SysUser user) {
{
return userMapper.updateUser(user); return userMapper.updateUser(user);
} }
@@ -374,8 +355,7 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int resetUserPwd(Long userId, String password) public int resetUserPwd(Long userId, String password) {
{
return userMapper.resetUserPwd(userId, password); return userMapper.resetUserPwd(userId, password);
} }
@@ -384,8 +364,7 @@ public class SysUserServiceImpl implements ISysUserService
* *
* @param user 用户对象 * @param user 用户对象
*/ */
public void insertUserRole(SysUser user) public void insertUserRole(SysUser user) {
{
this.insertUserRole(user.getUserId(), user.getRoleIds()); this.insertUserRole(user.getUserId(), user.getRoleIds());
} }
@@ -394,15 +373,12 @@ public class SysUserServiceImpl implements ISysUserService
* *
* @param user 用户对象 * @param user 用户对象
*/ */
public void insertUserPost(SysUser user) public void insertUserPost(SysUser user) {
{
Long[] posts = user.getPostIds(); Long[] posts = user.getPostIds();
if (StringUtils.isNotEmpty(posts)) if (StringUtils.isNotEmpty(posts)) {
{
// 新增用户与岗位管理 // 新增用户与岗位管理
List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length); List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
for (Long postId : posts) for (Long postId : posts) {
{
SysUserPost up = new SysUserPost(); SysUserPost up = new SysUserPost();
up.setUserId(user.getUserId()); up.setUserId(user.getUserId());
up.setPostId(postId); up.setPostId(postId);
@@ -418,14 +394,11 @@ public class SysUserServiceImpl implements ISysUserService
* @param userId 用户ID * @param userId 用户ID
* @param roleIds 角色组 * @param roleIds 角色组
*/ */
public void insertUserRole(Long userId, Long[] roleIds) public void insertUserRole(Long userId, Long[] roleIds) {
{ if (StringUtils.isNotEmpty(roleIds)) {
if (StringUtils.isNotEmpty(roleIds))
{
// 新增用户与角色管理 // 新增用户与角色管理
List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length); List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
for (Long roleId : roleIds) for (Long roleId : roleIds) {
{
SysUserRole ur = new SysUserRole(); SysUserRole ur = new SysUserRole();
ur.setUserId(userId); ur.setUserId(userId);
ur.setRoleId(roleId); ur.setRoleId(roleId);
@@ -443,8 +416,7 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@Transactional @Transactional
public int deleteUserById(Long userId) public int deleteUserById(Long userId) {
{
// 删除用户与角色关联 // 删除用户与角色关联
userRoleMapper.deleteUserRoleByUserId(userId); userRoleMapper.deleteUserRoleByUserId(userId);
// 删除用户与岗位表 // 删除用户与岗位表
@@ -460,10 +432,8 @@ public class SysUserServiceImpl implements ISysUserService
*/ */
@Override @Override
@Transactional @Transactional
public int deleteUserByIds(Long[] userIds) public int deleteUserByIds(Long[] userIds) {
{ for (Long userId : userIds) {
for (Long userId : userIds)
{
checkUserAllowed(new SysUser(userId)); checkUserAllowed(new SysUser(userId));
checkUserDataScope(userId); checkUserDataScope(userId);
} }
@@ -483,24 +453,19 @@ public class SysUserServiceImpl implements ISysUserService
* @return 结果 * @return 结果
*/ */
@Override @Override
public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) {
{ if (StringUtils.isNull(userList) || userList.size() == 0) {
if (StringUtils.isNull(userList) || userList.size() == 0)
{
throw new ServiceException("导入用户数据不能为空!"); throw new ServiceException("导入用户数据不能为空!");
} }
int successNum = 0; int successNum = 0;
int failureNum = 0; int failureNum = 0;
StringBuilder successMsg = new StringBuilder(); StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder();
for (SysUser user : userList) for (SysUser user : userList) {
{ try {
try
{
// 验证是否存在这个用户 // 验证是否存在这个用户
SysUser u = userMapper.selectUserByUserName(user.getUserName()); SysUser u = userMapper.selectUserByUserName(user.getUserName());
if (StringUtils.isNull(u)) if (StringUtils.isNull(u)) {
{
BeanValidators.validateWithException(validator, user); BeanValidators.validateWithException(validator, user);
deptService.checkDeptDataScope(user.getDeptId()); deptService.checkDeptDataScope(user.getDeptId());
String password = configService.selectConfigByKey("sys.user.initPassword"); String password = configService.selectConfigByKey("sys.user.initPassword");
@@ -509,9 +474,7 @@ public class SysUserServiceImpl implements ISysUserService
userMapper.insertUser(user); userMapper.insertUser(user);
successNum++; successNum++;
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功"); successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
} } else if (isUpdateSupport) {
else if (isUpdateSupport)
{
BeanValidators.validateWithException(validator, user); BeanValidators.validateWithException(validator, user);
checkUserAllowed(u); checkUserAllowed(u);
checkUserDataScope(u.getUserId()); checkUserDataScope(u.getUserId());
@@ -521,28 +484,21 @@ public class SysUserServiceImpl implements ISysUserService
userMapper.updateUser(user); userMapper.updateUser(user);
successNum++; successNum++;
successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功"); successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
} } else {
else
{
failureNum++; failureNum++;
failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在"); failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
} }
} } catch (Exception e) {
catch (Exception e)
{
failureNum++; failureNum++;
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:";
failureMsg.append(msg + e.getMessage()); failureMsg.append(msg + e.getMessage());
log.error(msg, e); log.error(msg, e);
} }
} }
if (failureNum > 0) if (failureNum > 0) {
{
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString()); throw new ServiceException(failureMsg.toString());
} } else {
else
{
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
} }
return successMsg.toString(); return successMsg.toString();

View File

@@ -48,7 +48,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectUserVo"> <sql id="selectUserVo">
select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_by, u.create_time, u.remark, select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex,
u.status, u.del_flag, u.login_ip, u.login_date, u.pwd_update_date, u.create_by, u.create_time, u.remark,
d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
from sys_user u from sys_user u
@@ -58,7 +59,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql> </sql>
<select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status,
u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user
u
left join sys_dept d on u.dept_id = d.dept_id left join sys_dept d on u.dept_id = d.dept_id
where u.del_flag = '0' where u.del_flag = '0'
<if test="userId != null and userId != 0"> <if test="userId != null and userId != 0">
@@ -80,7 +83,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND date_format(u.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d') AND date_format(u.create_time,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if> </if>
<if test="deptId != null and deptId != 0"> <if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) )) AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId},
ancestors) ))
</if> </if>
<!-- 数据范围过滤 --> <!-- 数据范围过滤 -->
${params.dataScope} ${params.dataScope}
@@ -110,7 +114,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
left join sys_user_role ur on u.user_id = ur.user_id left join sys_user_role ur on u.user_id = ur.user_id
left join sys_role r on r.role_id = ur.role_id left join sys_role r on r.role_id = ur.role_id
where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL) where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId}) and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and
ur.role_id = #{roleId})
<if test="userName != null and userName != ''"> <if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%') AND u.user_name like concat('%', #{userName}, '%')
</if> </if>
@@ -205,6 +210,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update sys_user set avatar = #{avatar} where user_id = #{userId} update sys_user set avatar = #{avatar} where user_id = #{userId}
</update> </update>
<update id="updateLoginInfo" parameterType="SysUser">
update sys_user set login_ip = #{loginIp}, login_date = #{loginDate} where user_id = #{userId}
</update>
<update id="resetUserPwd" parameterType="SysUser"> <update id="resetUserPwd" parameterType="SysUser">
update sys_user set pwd_update_date = sysdate(), password = #{password} where user_id = #{userId} update sys_user set pwd_update_date = sysdate(), password = #{password} where user_id = #{userId}
</update> </update>