LIVE_YE 2 lat temu
rodzic
commit
3903310293

+ 113 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/PwdCheckUtil.java

@@ -0,0 +1,113 @@
+package com.ruoyi.web.controller;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * @Author: tjf
+ * @Date: 2022/10/10 9:24
+ * @Describe:
+ */
+public class PwdCheckUtil {
+    //定义特殊字符
+    public static String SPECIAL_CHAR = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
+
+    /**
+     * @brief   检测密码中字符长度
+     * @param[in] password            密码字符串
+     * @return  符合长度要求 返回true
+     */
+    public static boolean checkPasswordLength(String password, String minNum, String maxNum) {
+        boolean flag =false;
+        if (StringUtils.isBlank(maxNum))  {
+            minNum = StringUtils.isBlank(minNum) ? "0":minNum;
+            if (password.length() >= Integer.parseInt(minNum)) {
+                flag = true;
+            }
+        } else {
+            minNum = StringUtils.isBlank(minNum) ? "0":minNum;
+            if (password.length() >= Integer.parseInt(minNum) &&
+                    password.length() <= Integer.parseInt(maxNum)) {
+                flag = true;
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * @brief   检测密码中是否包含数字
+     * @param[in] password            密码字符串
+     * @return  包含数字 返回true
+     */
+    public static boolean checkContainDigit(String password) {
+        char[] chPass = password.toCharArray();
+        for (int i = 0; i < chPass.length; i++) {
+            if (Character.isDigit(chPass[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @brief   检测密码中是否包含字母(不区分大小写)
+     * @param[in] password            密码字符串
+     * @return  包含字母 返回true
+     */
+    public static boolean checkContainCase(String password) {
+        char[] chPass = password.toCharArray();
+        for (int i = 0; i < chPass.length; i++) {
+            if (Character.isLetter(chPass[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * @brief   检测密码中是否包含小写字母
+     * @param[in] password            密码字符串
+     * @return  包含小写字母 返回true
+     */
+    public static boolean checkContainLowerCase(String password) {
+        char[] chPass = password.toCharArray();
+        for (int i = 0; i < chPass.length; i++) {
+            if (Character.isLowerCase(chPass[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * @brief   检测密码中是否包含大写字母
+     * @param[in] password            密码字符串
+     * @return  包含大写字母 返回true
+     */
+    public static boolean checkContainUpperCase(String password) {
+        char[] chPass = password.toCharArray();
+        for (int i = 0; i < chPass.length; i++) {
+            if (Character.isUpperCase(chPass[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * @brief   检测密码中是否包含特殊符号
+     * @param[in] password            密码字符串
+     * @return  包含特殊符号 返回true
+     */
+    public static boolean checkContainSpecialChar(String password) {
+        char[] chPass = password.toCharArray();
+        for (int i = 0; i < chPass.length; i++) {
+            if (SPECIAL_CHAR.indexOf(chPass[i]) != -1) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

+ 69 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -1,5 +1,9 @@
 package com.ruoyi.web.controller.system;
 
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.web.controller.PwdCheckUtil;
+import org.assertj.core.util.Preconditions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -24,6 +28,8 @@ import com.ruoyi.common.utils.file.MimeTypeUtils;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysUserService;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * 个人信息 业务处理
  * 
@@ -39,6 +45,9 @@ public class SysProfileController extends BaseController
     @Autowired
     private TokenService tokenService;
 
+    @Autowired
+    private RedisCache redisCache;
+
     /**
      * 个人信息
      */
@@ -95,6 +104,9 @@ public class SysProfileController extends BaseController
     @PostMapping("/updatePwd")
     public AjaxResult updatePwd(String oldPassword, String newPassword)
     {
+        if ("1".equals(checkStrongPwd(newPassword))) {
+            return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
+        }
         LoginUser loginUser = getLoginUser();
         String userName = loginUser.getUsername();
         String password = loginUser.getPassword();
@@ -111,11 +123,46 @@ public class SysProfileController extends BaseController
             // 更新缓存用户密码
             loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
             tokenService.setLoginUser(loginUser);
+
+            //将修改后的密码存入redis并设置有效时间60天
+            redisCache.setCacheObject(Constants.PASSWORD_USER+"-"+userName, "60", Constants.EFFECTIVE_DATE, TimeUnit.DAYS);
+
             return AjaxResult.success();
         }
         return AjaxResult.error("修改密码异常,请联系管理员");
     }
 
+
+    @PostMapping("/resetPwdLogin")
+    public AjaxResult resetPwdLogin(@RequestParam("userName") String userName,@RequestParam("oldPassword") String oldPassword,@RequestParam("newPassword") String newPassword) {
+        //userService.checkUserAllowed(user);
+        if ("admin".equals(userName)){
+            return AjaxResult.success("不允许操作超级管理员");
+        }
+        SysUser user = userService.selectUserByUserName(userName);
+        if (user == null){
+            return AjaxResult.success("当前用户不存在");
+        }
+        String password = user.getPassword();
+        if (!SecurityUtils.matchesPassword(oldPassword, password))
+        {
+            return AjaxResult.success("修改密码失败,旧密码错误");
+        }
+        if (SecurityUtils.matchesPassword(newPassword, password))
+        {
+            return AjaxResult.success("新密码不能与旧密码相同");
+        }
+
+        if ("1".equals(checkStrongPwd(newPassword))) {
+            return AjaxResult.success("密码必须包含数字、大小写字母、特殊符号且大于8位");
+        }
+        user.setPassword(SecurityUtils.encryptPassword(newPassword));
+        user.setUpdateBy(userName);
+        redisCache.setCacheObject(Constants.PASSWORD_USER+"-"+userName, "60", Constants.EFFECTIVE_DATE, TimeUnit.DAYS);
+        return toAjax(userService.resetUserPwd(userName, user.getPassword()));
+    }
+
+
     /**
      * 头像上传
      */
@@ -139,4 +186,26 @@ public class SysProfileController extends BaseController
         }
         return AjaxResult.error("上传图片异常,请联系管理员");
     }
+
+    /**
+     * @brief   检测密码复杂度是否为 强
+     * @param[in] password  密码字符串
+     * @return  符合长度要求 返回true
+     */
+    public static String checkStrongPwd(String pwd) {
+        try {
+            Preconditions.checkNotNull(pwd);
+            if (!PwdCheckUtil.checkPasswordLength(pwd, "8", null)
+                    || !PwdCheckUtil.checkContainLowerCase(pwd)
+                    || !PwdCheckUtil.checkContainUpperCase(pwd)
+                    || !PwdCheckUtil.checkContainDigit(pwd)
+                    || !PwdCheckUtil.checkContainSpecialChar(pwd)
+            ) {
+                return "1";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "0";
+    }
 }

+ 50 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -1,11 +1,16 @@
 package com.ruoyi.web.controller.system;
 
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletResponse;
 import javax.swing.*;
 
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.web.controller.PwdCheckUtil;
 import org.apache.commons.lang3.ArrayUtils;
+import org.assertj.core.util.Preconditions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
@@ -51,6 +56,9 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysPostService postService;
 
+    @Autowired
+    private RedisCache redisCache;
+
     /**
      * 获取用户列表
      */
@@ -136,9 +144,18 @@ public class SysUserController extends BaseController
         {
             return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
         }
+
+        if ("1".equals(checkStrongPwd(user.getPassword()))) {
+            return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
+        }
+
         user.setCreateBy(getUsername());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
-        return toAjax(userService.insertUser(user));
+        int rows = userService.insertUser(user);
+        if(rows>0){
+            redisCache.setCacheObject(Constants.PASSWORD_USER+"-"+user.getUserName(), "60", Constants.EFFECTIVE_DATE, TimeUnit.DAYS);
+        }
+        return toAjax(rows);
     }
 
     /**
@@ -188,10 +205,19 @@ public class SysUserController extends BaseController
     @PostMapping("/resetPwd")
     public AjaxResult resetPwd(@RequestBody SysUser user)
     {
+
+        if ("1".equals(checkStrongPwd(user.getPassword()))) {
+            return AjaxResult.error("密码必须包含数字、大小写字母、特殊符号且大于8位");
+        }
+
         userService.checkUserAllowed(user);
         userService.checkUserDataScope(user.getUserId());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         user.setUpdateBy(getUsername());
+
+        //将修改后的密码存入redis并设置有效时间60天
+        redisCache.setCacheObject(Constants.PASSWORD_USER+"-"+getUsername(), "60", Constants.EFFECTIVE_DATE, TimeUnit.DAYS);
+
         return toAjax(userService.resetPwd(user));
     }
 
@@ -260,4 +286,27 @@ public class SysUserController extends BaseController
         }
 
     }
+
+    /**
+     * @brief   检测密码复杂度是否为 强
+     * @param[in] password  密码字符串
+     * @return  符合长度要求 返回true
+     */
+    public static String checkStrongPwd(String pwd) {
+        try {
+            Preconditions.checkNotNull(pwd);
+            if (!PwdCheckUtil.checkPasswordLength(pwd, "8", null)
+                    || !PwdCheckUtil.checkContainLowerCase(pwd)
+                    || !PwdCheckUtil.checkContainUpperCase(pwd)
+                    || !PwdCheckUtil.checkContainDigit(pwd)
+                    || !PwdCheckUtil.checkContainSpecialChar(pwd)
+            ) {
+                return "1";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "0";
+    }
+
 }

+ 1 - 1
ruoyi-admin/src/main/resources/application-prod.yml

@@ -32,7 +32,7 @@ spring:
             slave:
                 # 从数据源开关/默认关闭
                 enabled: true
-                url: jdbc:mysql://60.171.171.235:3386/qss_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
+                url: jdbc:mysql://172.27.189.57:3386/qss_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
                 username: qss_db
                 password: S6u269%6
             # 初始连接数

+ 1 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -81,6 +81,6 @@ xss:
   # 过滤开关
   enabled: true
   # 排除链接(多个用逗号分隔)
-  excludes: /system/notice,/system/merchants,/system/guide,/system/use,/system/welfare,/system/data,/system/foreign
+  excludes: /system/notice,/system/merchants,/system/guide,/system/use,/system/welfare,/system/data,/system/foreign,/system/user/profile/resetPwdLogin
   # 匹配链接
   urlPatterns: /system/*,/monitor/*,/tool/*

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages.properties

@@ -4,6 +4,7 @@ user.jcaptcha.error=验证码错误
 user.jcaptcha.expire=验证码已失效
 user.not.exists=用户不存在/密码错误
 user.password.not.match=用户不存在/密码错误
+user.password.not.login=长时间未登录,修改密码后重新登录
 user.password.retry.limit.count=密码输入错误{0}次
 user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
 user.password.delete=对不起,您的账号已被删除

+ 10 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -64,6 +64,11 @@ public class Constants
      */
     public static final Integer CAPTCHA_EXPIRATION = 2;
 
+    /**
+     * 账号有效期(天)
+     */
+    public static final Integer EFFECTIVE_DATE = 60;
+
     /**
      * 账号密码输入错误间隔
      */
@@ -139,4 +144,9 @@ public class Constants
      */
     public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
             "org.springframework", "org.apache", "com.ruoyi.common.utils.file" };
+
+    /**
+     * 2个月内修改密码
+     */
+    public static final String PASSWORD_USER = "password_user";
 }

+ 16 - 0
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotLoginException.java

@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 用户超过2个月没有登录
+ * 
+ * @author ruoyi
+ */
+public class UserPasswordNotLoginException extends UserException
+{
+    private static final long serialVersionUID = 1L;
+
+    public UserPasswordNotLoginException()
+    {
+        super("user.password.not.login", null);
+    }
+}

+ 1 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -109,7 +109,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 // 过滤请求
                 .authorizeRequests()
                 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
-                .antMatchers("/login", "/register", "/captchaImage","/system/data","/system/user/updateAll","/system/data/foreign/list").anonymous()
+                .antMatchers("/login", "/register", "/captchaImage","/system/data","/system/user/updateAll","/system/data/foreign/list","/system/user/profile/resetPwdLogin").anonymous()
                 // 静态资源,可匿名访问
                 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
                 .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()

+ 12 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -2,7 +2,7 @@ package com.ruoyi.framework.web.service;
 
 import javax.annotation.Resource;
 
-import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
+import com.ruoyi.common.exception.user.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
@@ -15,9 +15,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.exception.user.CaptchaException;
-import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.MessageUtils;
 import com.ruoyi.common.utils.ServletUtils;
@@ -74,6 +71,16 @@ public class SysLoginService
         // 用户验证
         Authentication authentication = null;
 
+        //判断2个月内是否修改密码,排除admin
+        if(StringUtils.isNotEmpty(username) && !"admin".equals(username)){
+            String isUpdate = redisCache.getCacheObject(Constants.PASSWORD_USER+"-"+username);
+            if(StringUtils.isEmpty(isUpdate)){
+                //自定义异常类
+                throw new UserPasswordNotLoginException();
+            }
+        }
+
+        //查询登录错误次数
         String num = redisCache.getCacheObject(username);
         if(StringUtils.isEmpty(num)){
             num = "0";
@@ -93,6 +100,7 @@ public class SysLoginService
                 if(Integer.parseInt(num) == 5){
                     throw new UserPasswordRetryLimitExceedException(5,3);
                 }
+                //存入redis登录错误次数
                 redisCache.setCacheObject(username, String.valueOf(Integer.parseInt(num)+1), Constants.USERNAME_EXPIRATION, TimeUnit.MINUTES);
                 AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                 throw new UserPasswordNotMatchException();