From 1b140fcc838bcdeb1d12ee9539ed026e4bf3f573 Mon Sep 17 00:00:00 2001 From: devttl Date: Sat, 20 Sep 2025 21:19:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=98=B2=E7=9B=97=E9=93=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 7 + .../devttl/common/filter/RefererFilter.java | 63 +++ .../devttl/framework/config/FilterConfig.java | 45 +- .../web/service/SysLoginService.java | 99 ++-- .../devttl/system/mapper/SysUserMapper.java | 47 +- .../system/service/ISysUserService.java | 71 +-- .../service/impl/SysUserServiceImpl.java | 256 +++++------ .../resources/mapper/system/SysUserMapper.xml | 423 +++++++++--------- 8 files changed, 530 insertions(+), 481 deletions(-) create mode 100644 devttl-common/src/main/java/com/devttl/common/filter/RefererFilter.java diff --git a/devttl-admin/src/main/resources/application.yml b/devttl-admin/src/main/resources/application.yml index d158b81..95776d7 100644 --- a/devttl-admin/src/main/resources/application.yml +++ b/devttl-admin/src/main/resources/application.yml @@ -127,6 +127,13 @@ springdoc: paths-to-match: '/**' 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: # 过滤开关 diff --git a/devttl-common/src/main/java/com/devttl/common/filter/RefererFilter.java b/devttl-common/src/main/java/com/devttl/common/filter/RefererFilter.java new file mode 100644 index 0000000..96f1a66 --- /dev/null +++ b/devttl-common/src/main/java/com/devttl/common/filter/RefererFilter.java @@ -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 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() { + + } +} \ No newline at end of file diff --git a/devttl-framework/src/main/java/com/devttl/framework/config/FilterConfig.java b/devttl-framework/src/main/java/com/devttl/framework/config/FilterConfig.java index e572da7..9b96fb1 100644 --- a/devttl-framework/src/main/java/com/devttl/framework/config/FilterConfig.java +++ b/devttl-framework/src/main/java/com/devttl/framework/config/FilterConfig.java @@ -1,16 +1,19 @@ package com.devttl.framework.config; -import java.util.HashMap; -import java.util.Map; +import com.devttl.common.constant.Constants; +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 org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import com.devttl.common.filter.RepeatableFilter; -import com.devttl.common.filter.XssFilter; -import com.devttl.common.utils.StringUtils; + +import java.util.HashMap; +import java.util.Map; /** * Filter配置 @@ -18,19 +21,20 @@ import com.devttl.common.utils.StringUtils; * @author devttl */ @Configuration -public class FilterConfig -{ +public class FilterConfig { @Value("${xss.excludes}") private String excludes; @Value("${xss.urlPatterns}") private String urlPatterns; - @SuppressWarnings({ "rawtypes", "unchecked" }) + @Value("${referer.allowed-domains}") + private String allowedDomains; + + @SuppressWarnings({"rawtypes", "unchecked"}) @Bean @ConditionalOnProperty(value = "xss.enabled", havingValue = "true") - public FilterRegistrationBean xssFilterRegistration() - { + public FilterRegistrationBean xssFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setDispatcherTypes(DispatcherType.REQUEST); registration.setFilter(new XssFilter()); @@ -43,10 +47,25 @@ public class FilterConfig return registration; } - @SuppressWarnings({ "rawtypes", "unchecked" }) + @SuppressWarnings({"rawtypes", "unchecked"}) @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 initParameters = new HashMap(); + initParameters.put("allowedDomains", allowedDomains); + registration.setInitParameters(initParameters); + return registration; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Bean + public FilterRegistrationBean someFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new RepeatableFilter()); registration.addUrlPatterns("/*"); diff --git a/devttl-framework/src/main/java/com/devttl/framework/web/service/SysLoginService.java b/devttl-framework/src/main/java/com/devttl/framework/web/service/SysLoginService.java index 5f98c5f..99ae2b1 100644 --- a/devttl-framework/src/main/java/com/devttl/framework/web/service/SysLoginService.java +++ b/devttl-framework/src/main/java/com/devttl/framework/web/service/SysLoginService.java @@ -1,24 +1,12 @@ 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.Constants; 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.redis.RedisCache; import com.devttl.common.exception.ServiceException; -import com.devttl.common.exception.user.BlackListException; -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.exception.user.*; import com.devttl.common.utils.DateUtils; import com.devttl.common.utils.MessageUtils; import com.devttl.common.utils.StringUtils; @@ -28,15 +16,22 @@ import com.devttl.framework.manager.factory.AsyncFactory; import com.devttl.framework.security.context.AuthenticationContextHolder; import com.devttl.system.service.ISysConfigService; 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; + /** * 登录校验方法 - * + * * @author devttl */ @Component -public class SysLoginService -{ +public class SysLoginService { @Autowired private TokenService tokenService; @@ -45,7 +40,7 @@ public class SysLoginService @Autowired private RedisCache redisCache; - + @Autowired private ISysUserService userService; @@ -54,43 +49,34 @@ public class SysLoginService /** * 登录验证 - * + * * @param username 用户名 * @param password 密码 - * @param code 验证码 - * @param uuid 唯一标识 + * @param code 验证码 + * @param uuid 唯一标识 * @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); // 登录前置校验 loginPreCheck(username, password); // 用户验证 Authentication authentication = null; - try - { + try { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); AuthenticationContextHolder.setContext(authenticationToken); // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername authentication = authenticationManager.authenticate(authenticationToken); - } - catch (Exception e) - { - if (e instanceof BadCredentialsException) - { + } catch (Exception e) { + if (e instanceof BadCredentialsException) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); throw new UserPasswordNotMatchException(); - } - else - { + } else { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); throw new ServiceException(e.getMessage()); } - } - finally - { + } finally { AuthenticationContextHolder.clearContext(); } AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); @@ -102,27 +88,23 @@ public class SysLoginService /** * 校验验证码 - * + * * @param username 用户名 - * @param code 验证码 - * @param uuid 唯一标识 + * @param code 验证码 + * @param uuid 唯一标识 * @return 结果 */ - public void validateCaptcha(String username, String code, String uuid) - { + public void validateCaptcha(String username, String code, String uuid) { boolean captchaEnabled = configService.selectCaptchaEnabled(); - if (captchaEnabled) - { + if (captchaEnabled) { String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); 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"))); throw new CaptchaExpireException(); } 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"))); throw new CaptchaException(); } @@ -131,35 +113,31 @@ public class SysLoginService /** * 登录前置校验 + * * @param username 用户名 * @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"))); throw new UserNotExistsException(); } // 密码如果不在指定范围内 错误 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"))); throw new UserPasswordNotMatchException(); } // 用户名不在指定范围内 错误 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"))); throw new UserPasswordNotMatchException(); } // IP黑名单校验 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"))); throw new BlackListException(); } @@ -170,12 +148,7 @@ public class SysLoginService * * @param userId 用户ID */ - public void recordLoginInfo(Long userId) - { - SysUser sysUser = new SysUser(); - sysUser.setUserId(userId); - sysUser.setLoginIp(IpUtils.getIpAddr()); - sysUser.setLoginDate(DateUtils.getNowDate()); - userService.updateUserProfile(sysUser); + public void recordLoginInfo(Long userId) { + userService.updateLoginInfo(userId, IpUtils.getIpAddr(), DateUtils.getNowDate()); } } diff --git a/devttl-system/src/main/java/com/devttl/system/mapper/SysUserMapper.java b/devttl-system/src/main/java/com/devttl/system/mapper/SysUserMapper.java index 7e0da66..e0e15e6 100644 --- a/devttl-system/src/main/java/com/devttl/system/mapper/SysUserMapper.java +++ b/devttl-system/src/main/java/com/devttl/system/mapper/SysUserMapper.java @@ -1,19 +1,20 @@ package com.devttl.system.mapper; -import java.util.List; -import org.apache.ibatis.annotations.Param; import com.devttl.common.core.domain.entity.SysUser; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; /** * 用户表 数据层 - * + * * @author devttl */ -public interface SysUserMapper -{ +public interface SysUserMapper { /** * 根据条件分页查询用户列表 - * + * * @param sysUser 用户信息 * @return 用户信息集合信息 */ @@ -21,7 +22,7 @@ public interface SysUserMapper /** * 根据条件分页查询已配用户角色列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @@ -29,7 +30,7 @@ public interface SysUserMapper /** * 根据条件分页查询未分配用户角色列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @@ -37,7 +38,7 @@ public interface SysUserMapper /** * 通过用户名查询用户 - * + * * @param userName 用户名 * @return 用户对象信息 */ @@ -45,7 +46,7 @@ public interface SysUserMapper /** * 通过用户ID查询用户 - * + * * @param userId 用户ID * @return 用户对象信息 */ @@ -53,7 +54,7 @@ public interface SysUserMapper /** * 新增用户信息 - * + * * @param user 用户信息 * @return 结果 */ @@ -61,7 +62,7 @@ public interface SysUserMapper /** * 修改用户信息 - * + * * @param user 用户信息 * @return 结果 */ @@ -69,17 +70,27 @@ public interface SysUserMapper /** * 修改用户头像 - * + * * @param userId 用户ID * @param avatar 头像地址 * @return 结果 */ 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); + /** * 重置用户密码 - * - * @param userId 用户ID + * + * @param userId 用户ID * @param password 密码 * @return 结果 */ @@ -87,7 +98,7 @@ public interface SysUserMapper /** * 通过用户ID删除用户 - * + * * @param userId 用户ID * @return 结果 */ @@ -95,7 +106,7 @@ public interface SysUserMapper /** * 批量删除用户信息 - * + * * @param userIds 需要删除的用户ID * @return 结果 */ @@ -103,7 +114,7 @@ public interface SysUserMapper /** * 校验用户名称是否唯一 - * + * * @param userName 用户名称 * @return 结果 */ diff --git a/devttl-system/src/main/java/com/devttl/system/service/ISysUserService.java b/devttl-system/src/main/java/com/devttl/system/service/ISysUserService.java index c526457..2ae43ac 100644 --- a/devttl-system/src/main/java/com/devttl/system/service/ISysUserService.java +++ b/devttl-system/src/main/java/com/devttl/system/service/ISysUserService.java @@ -1,18 +1,19 @@ package com.devttl.system.service; -import java.util.List; import com.devttl.common.core.domain.entity.SysUser; +import java.util.Date; +import java.util.List; + /** * 用户 业务层 - * + * * @author devttl */ -public interface ISysUserService -{ +public interface ISysUserService { /** * 根据条件分页查询用户列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @@ -20,7 +21,7 @@ public interface ISysUserService /** * 根据条件分页查询已分配用户角色列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @@ -28,7 +29,7 @@ public interface ISysUserService /** * 根据条件分页查询未分配用户角色列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @@ -36,7 +37,7 @@ public interface ISysUserService /** * 通过用户名查询用户 - * + * * @param userName 用户名 * @return 用户对象信息 */ @@ -44,7 +45,7 @@ public interface ISysUserService /** * 通过用户ID查询用户 - * + * * @param userId 用户ID * @return 用户对象信息 */ @@ -52,7 +53,7 @@ public interface ISysUserService /** * 根据用户ID查询用户所属角色组 - * + * * @param userName 用户名 * @return 结果 */ @@ -60,7 +61,7 @@ public interface ISysUserService /** * 根据用户ID查询用户所属岗位组 - * + * * @param userName 用户名 * @return 结果 */ @@ -68,7 +69,7 @@ public interface ISysUserService /** * 校验用户名称是否唯一 - * + * * @param user 用户信息 * @return 结果 */ @@ -92,21 +93,21 @@ public interface ISysUserService /** * 校验用户是否允许操作 - * + * * @param user 用户信息 */ public void checkUserAllowed(SysUser user); /** * 校验用户是否有数据权限 - * + * * @param userId 用户id */ public void checkUserDataScope(Long userId); /** * 新增用户信息 - * + * * @param user 用户信息 * @return 结果 */ @@ -114,7 +115,7 @@ public interface ISysUserService /** * 注册用户信息 - * + * * @param user 用户信息 * @return 结果 */ @@ -122,7 +123,7 @@ public interface ISysUserService /** * 修改用户信息 - * + * * @param user 用户信息 * @return 结果 */ @@ -130,15 +131,15 @@ public interface ISysUserService /** * 用户授权角色 - * - * @param userId 用户ID + * + * @param userId 用户ID * @param roleIds 角色组 */ public void insertUserAuth(Long userId, Long[] roleIds); /** * 修改用户状态 - * + * * @param user 用户信息 * @return 结果 */ @@ -146,7 +147,7 @@ public interface ISysUserService /** * 修改用户基本信息 - * + * * @param user 用户信息 * @return 结果 */ @@ -154,16 +155,26 @@ public interface ISysUserService /** * 修改用户头像 - * + * * @param userId 用户ID * @param avatar 头像地址 * @return 结果 */ 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); + /** * 重置用户密码 - * + * * @param user 用户信息 * @return 结果 */ @@ -171,8 +182,8 @@ public interface ISysUserService /** * 重置用户密码 - * - * @param userId 用户ID + * + * @param userId 用户ID * @param password 密码 * @return 结果 */ @@ -180,7 +191,7 @@ public interface ISysUserService /** * 通过用户ID删除用户 - * + * * @param userId 用户ID * @return 结果 */ @@ -188,7 +199,7 @@ public interface ISysUserService /** * 批量删除用户信息 - * + * * @param userIds 需要删除的用户ID * @return 结果 */ @@ -196,10 +207,10 @@ public interface ISysUserService /** * 导入用户数据 - * - * @param userList 用户数据列表 + * + * @param userList 用户数据列表 * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 - * @param operName 操作用户 + * @param operName 操作用户 * @return 结果 */ public String importUser(List userList, Boolean isUpdateSupport, String operName); diff --git a/devttl-system/src/main/java/com/devttl/system/service/impl/SysUserServiceImpl.java b/devttl-system/src/main/java/com/devttl/system/service/impl/SysUserServiceImpl.java index 8cb0b3e..99cb7f8 100644 --- a/devttl-system/src/main/java/com/devttl/system/service/impl/SysUserServiceImpl.java +++ b/devttl-system/src/main/java/com/devttl/system/service/impl/SysUserServiceImpl.java @@ -1,15 +1,5 @@ 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.constant.UserConstants; import com.devttl.common.core.domain.entity.SysRole; @@ -22,23 +12,30 @@ import com.devttl.common.utils.spring.SpringUtils; import com.devttl.system.domain.SysPost; import com.devttl.system.domain.SysUserPost; import com.devttl.system.domain.SysUserRole; -import com.devttl.system.mapper.SysPostMapper; -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.mapper.*; import com.devttl.system.service.ISysConfigService; import com.devttl.system.service.ISysDeptService; 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; /** * 用户 业务层处理 - * + * * @author devttl */ @Service -public class SysUserServiceImpl implements ISysUserService -{ +public class SysUserServiceImpl implements ISysUserService { private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); @Autowired @@ -67,79 +64,72 @@ public class SysUserServiceImpl implements ISysUserService /** * 根据条件分页查询用户列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") - public List selectUserList(SysUser user) - { + public List selectUserList(SysUser user) { return userMapper.selectUserList(user); } /** * 根据条件分页查询已分配用户角色列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") - public List selectAllocatedList(SysUser user) - { + public List selectAllocatedList(SysUser user) { return userMapper.selectAllocatedList(user); } /** * 根据条件分页查询未分配用户角色列表 - * + * * @param user 用户信息 * @return 用户信息集合信息 */ @Override @DataScope(deptAlias = "d", userAlias = "u") - public List selectUnallocatedList(SysUser user) - { + public List selectUnallocatedList(SysUser user) { return userMapper.selectUnallocatedList(user); } /** * 通过用户名查询用户 - * + * * @param userName 用户名 * @return 用户对象信息 */ @Override - public SysUser selectUserByUserName(String userName) - { + public SysUser selectUserByUserName(String userName) { return userMapper.selectUserByUserName(userName); } /** * 通过用户ID查询用户 - * + * * @param userId 用户ID * @return 用户对象信息 */ @Override - public SysUser selectUserById(Long userId) - { + public SysUser selectUserById(Long userId) { return userMapper.selectUserById(userId); } /** * 查询用户所属角色组 - * + * * @param userName 用户名 * @return 结果 */ @Override - public String selectUserRoleGroup(String userName) - { + public String selectUserRoleGroup(String userName) { List list = roleMapper.selectRolesByUserName(userName); - if (CollectionUtils.isEmpty(list)) - { + if (CollectionUtils.isEmpty(list)) { return StringUtils.EMPTY; } return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); @@ -147,16 +137,14 @@ public class SysUserServiceImpl implements ISysUserService /** * 查询用户所属岗位组 - * + * * @param userName 用户名 * @return 结果 */ @Override - public String selectUserPostGroup(String userName) - { + public String selectUserPostGroup(String userName) { List list = postMapper.selectPostsByUserName(userName); - if (CollectionUtils.isEmpty(list)) - { + if (CollectionUtils.isEmpty(list)) { return StringUtils.EMPTY; } return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); @@ -164,17 +152,15 @@ public class SysUserServiceImpl implements ISysUserService /** * 校验用户名称是否唯一 - * + * * @param user 用户信息 * @return 结果 */ @Override - public boolean checkUserNameUnique(SysUser user) - { + public boolean checkUserNameUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); 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.UNIQUE; @@ -187,12 +173,10 @@ public class SysUserServiceImpl implements ISysUserService * @return */ @Override - public boolean checkPhoneUnique(SysUser user) - { + public boolean checkPhoneUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); 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.UNIQUE; @@ -205,12 +189,10 @@ public class SysUserServiceImpl implements ISysUserService * @return */ @Override - public boolean checkEmailUnique(SysUser user) - { + public boolean checkEmailUnique(SysUser user) { Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); 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.UNIQUE; @@ -218,33 +200,28 @@ public class SysUserServiceImpl implements ISysUserService /** * 校验用户是否允许操作 - * + * * @param user 用户信息 */ @Override - public void checkUserAllowed(SysUser user) - { - if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) - { + public void checkUserAllowed(SysUser user) { + if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) { throw new ServiceException("不允许操作超级管理员用户"); } } /** * 校验用户是否有数据权限 - * + * * @param userId 用户id */ @Override - public void checkUserDataScope(Long userId) - { - if (!SysUser.isAdmin(SecurityUtils.getUserId())) - { + public void checkUserDataScope(Long userId) { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) { SysUser user = new SysUser(); user.setUserId(userId); List users = SpringUtils.getAopProxy(this).selectUserList(user); - if (StringUtils.isEmpty(users)) - { + if (StringUtils.isEmpty(users)) { throw new ServiceException("没有权限访问用户数据!"); } } @@ -252,14 +229,13 @@ public class SysUserServiceImpl implements ISysUserService /** * 新增保存用户信息 - * + * * @param user 用户信息 * @return 结果 */ @Override @Transactional - public int insertUser(SysUser user) - { + public int insertUser(SysUser user) { // 新增用户信息 int rows = userMapper.insertUser(user); // 新增用户岗位关联 @@ -271,26 +247,24 @@ public class SysUserServiceImpl implements ISysUserService /** * 注册用户信息 - * + * * @param user 用户信息 * @return 结果 */ @Override - public boolean registerUser(SysUser user) - { + public boolean registerUser(SysUser user) { return userMapper.insertUser(user) > 0; } /** * 修改保存用户信息 - * + * * @param user 用户信息 * @return 结果 */ @Override @Transactional - public int updateUser(SysUser user) - { + public int updateUser(SysUser user) { Long userId = user.getUserId(); // 删除用户与角色关联 userRoleMapper.deleteUserRoleByUserId(userId); @@ -305,104 +279,106 @@ public class SysUserServiceImpl implements ISysUserService /** * 用户授权角色 - * - * @param userId 用户ID + * + * @param userId 用户ID * @param roleIds 角色组 */ @Override @Transactional - public void insertUserAuth(Long userId, Long[] roleIds) - { + public void insertUserAuth(Long userId, Long[] roleIds) { userRoleMapper.deleteUserRoleByUserId(userId); insertUserRole(userId, roleIds); } /** * 修改用户状态 - * + * * @param user 用户信息 * @return 结果 */ @Override - public int updateUserStatus(SysUser user) - { + public int updateUserStatus(SysUser user) { return userMapper.updateUser(user); } /** * 修改用户基本信息 - * + * * @param user 用户信息 * @return 结果 */ @Override - public int updateUserProfile(SysUser user) - { + public int updateUserProfile(SysUser user) { return userMapper.updateUser(user); } /** * 修改用户头像 - * + * * @param userId 用户ID * @param avatar 头像地址 * @return 结果 */ @Override - public boolean updateUserAvatar(Long userId, String avatar) - { + public boolean updateUserAvatar(Long userId, String avatar) { 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); + } + /** * 重置用户密码 - * + * * @param user 用户信息 * @return 结果 */ @Override - public int resetPwd(SysUser user) - { + public int resetPwd(SysUser user) { return userMapper.updateUser(user); } /** * 重置用户密码 - * - * @param userId 用户ID + * + * @param userId 用户ID * @param password 密码 * @return 结果 */ @Override - public int resetUserPwd(Long userId, String password) - { + public int resetUserPwd(Long userId, String password) { return userMapper.resetUserPwd(userId, password); } /** * 新增用户角色信息 - * + * * @param user 用户对象 */ - public void insertUserRole(SysUser user) - { + public void insertUserRole(SysUser user) { this.insertUserRole(user.getUserId(), user.getRoleIds()); } /** * 新增用户岗位信息 - * + * * @param user 用户对象 */ - public void insertUserPost(SysUser user) - { + public void insertUserPost(SysUser user) { Long[] posts = user.getPostIds(); - if (StringUtils.isNotEmpty(posts)) - { + if (StringUtils.isNotEmpty(posts)) { // 新增用户与岗位管理 List list = new ArrayList(posts.length); - for (Long postId : posts) - { + for (Long postId : posts) { SysUserPost up = new SysUserPost(); up.setUserId(user.getUserId()); up.setPostId(postId); @@ -414,18 +390,15 @@ public class SysUserServiceImpl implements ISysUserService /** * 新增用户角色信息 - * - * @param userId 用户ID + * + * @param userId 用户ID * @param roleIds 角色组 */ - public void insertUserRole(Long userId, Long[] roleIds) - { - if (StringUtils.isNotEmpty(roleIds)) - { + public void insertUserRole(Long userId, Long[] roleIds) { + if (StringUtils.isNotEmpty(roleIds)) { // 新增用户与角色管理 List list = new ArrayList(roleIds.length); - for (Long roleId : roleIds) - { + for (Long roleId : roleIds) { SysUserRole ur = new SysUserRole(); ur.setUserId(userId); ur.setRoleId(roleId); @@ -437,14 +410,13 @@ public class SysUserServiceImpl implements ISysUserService /** * 通过用户ID删除用户 - * + * * @param userId 用户ID * @return 结果 */ @Override @Transactional - public int deleteUserById(Long userId) - { + public int deleteUserById(Long userId) { // 删除用户与角色关联 userRoleMapper.deleteUserRoleByUserId(userId); // 删除用户与岗位表 @@ -454,16 +426,14 @@ public class SysUserServiceImpl implements ISysUserService /** * 批量删除用户信息 - * + * * @param userIds 需要删除的用户ID * @return 结果 */ @Override @Transactional - public int deleteUserByIds(Long[] userIds) - { - for (Long userId : userIds) - { + public int deleteUserByIds(Long[] userIds) { + for (Long userId : userIds) { checkUserAllowed(new SysUser(userId)); checkUserDataScope(userId); } @@ -476,31 +446,26 @@ public class SysUserServiceImpl implements ISysUserService /** * 导入用户数据 - * - * @param userList 用户数据列表 + * + * @param userList 用户数据列表 * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 - * @param operName 操作用户 + * @param operName 操作用户 * @return 结果 */ @Override - public String importUser(List userList, Boolean isUpdateSupport, String operName) - { - if (StringUtils.isNull(userList) || userList.size() == 0) - { + public String importUser(List userList, Boolean isUpdateSupport, String operName) { + if (StringUtils.isNull(userList) || userList.size() == 0) { throw new ServiceException("导入用户数据不能为空!"); } int successNum = 0; int failureNum = 0; StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); - for (SysUser user : userList) - { - try - { + for (SysUser user : userList) { + try { // 验证是否存在这个用户 SysUser u = userMapper.selectUserByUserName(user.getUserName()); - if (StringUtils.isNull(u)) - { + if (StringUtils.isNull(u)) { BeanValidators.validateWithException(validator, user); deptService.checkDeptDataScope(user.getDeptId()); String password = configService.selectConfigByKey("sys.user.initPassword"); @@ -509,9 +474,7 @@ public class SysUserServiceImpl implements ISysUserService userMapper.insertUser(user); successNum++; successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 导入成功"); - } - else if (isUpdateSupport) - { + } else if (isUpdateSupport) { BeanValidators.validateWithException(validator, user); checkUserAllowed(u); checkUserDataScope(u.getUserId()); @@ -521,28 +484,21 @@ public class SysUserServiceImpl implements ISysUserService userMapper.updateUser(user); successNum++; successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 更新成功"); - } - else - { + } else { failureNum++; failureMsg.append("
" + failureNum + "、账号 " + user.getUserName() + " 已存在"); } - } - catch (Exception e) - { + } catch (Exception e) { failureNum++; String msg = "
" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; failureMsg.append(msg + e.getMessage()); log.error(msg, e); } } - if (failureNum > 0) - { + if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new ServiceException(failureMsg.toString()); - } - else - { + } else { successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); } return successMsg.toString(); diff --git a/devttl-system/src/main/resources/mapper/system/SysUserMapper.xml b/devttl-system/src/main/resources/mapper/system/SysUserMapper.xml index 0743f59..250171c 100644 --- a/devttl-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/devttl-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -1,223 +1,232 @@ + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + + + - + - - - - - - + + + + + + - - - 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, r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status from sys_user u - left join sys_dept d on u.dept_id = d.dept_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_dept d on u.dept_id = d.dept_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 - + - - - - - - - - - - - - - - - - - insert into sys_user( - user_id, - dept_id, - user_name, - nick_name, - email, - avatar, - phonenumber, - sex, - password, - status, - pwd_update_date, - create_by, - remark, - create_time - )values( - #{userId}, - #{deptId}, - #{userName}, - #{nickName}, - #{email}, - #{avatar}, - #{phonenumber}, - #{sex}, - #{password}, - #{status}, - #{pwdUpdateDate}, - #{createBy}, - #{remark}, - sysdate() - ) - - - - update sys_user - - dept_id = #{deptId}, - nick_name = #{nickName}, - email = #{email}, - phonenumber = #{phonenumber}, - sex = #{sex}, - avatar = #{avatar}, - password = #{password}, - status = #{status}, - login_ip = #{loginIp}, - login_date = #{loginDate}, - update_by = #{updateBy}, - remark = #{remark}, - update_time = sysdate() - - where user_id = #{userId} - - - - update sys_user set status = #{status} where user_id = #{userId} - - - - update sys_user set avatar = #{avatar} where user_id = #{userId} - - - - update sys_user set pwd_update_date = sysdate(), password = #{password} where user_id = #{userId} - - - - update sys_user set del_flag = '2' where user_id = #{userId} - - - - update sys_user set del_flag = '2' where user_id in - - #{userId} - - - + 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 + where u.del_flag = '0' + + AND u.user_id = #{userId} + + + AND u.user_name like concat('%', #{userName}, '%') + + + AND u.status = #{status} + + + AND u.phonenumber like concat('%', #{phonenumber}, '%') + + + AND date_format(u.create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d') + + + AND date_format(u.create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d') + + + AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, + ancestors) )) + + + ${params.dataScope} + + + + + + + + + + + + + + + + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + email, + avatar, + phonenumber, + sex, + password, + status, + pwd_update_date, + create_by, + remark, + create_time + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{pwdUpdateDate}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_user + + dept_id = #{deptId}, + nick_name = #{nickName}, + email = #{email}, + phonenumber = #{phonenumber}, + sex = #{sex}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where user_id = #{userId} + + + + update sys_user set status = #{status} where user_id = #{userId} + + + + update sys_user set avatar = #{avatar} where user_id = #{userId} + + + + update sys_user set login_ip = #{loginIp}, login_date = #{loginDate} where user_id = #{userId} + + + + update sys_user set pwd_update_date = sysdate(), password = #{password} where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id in + + #{userId} + + + \ No newline at end of file