tsurumure 5 månader sedan
förälder
incheckning
3b289707c5

+ 12 - 0
src/main/java/com/backendsys/modules/common/config/security/utils/CaptchaUtil.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.common.config.security.utils;
 
+import cn.hutool.core.convert.Convert;
 import com.backendsys.modules.common.config.redis.utils.RedisUtil;
 import com.google.code.kaptcha.Producer;
 import jakarta.servlet.ServletOutputStream;
@@ -30,6 +31,17 @@ public class CaptchaUtil {
     @Value("${CAPTCHA_DURATION}")
     private Integer CAPTCHA_DURATION;
 
+    /**
+     * 判断是否需要 验证码 (errCount: 错误次数)
+     */
+    public Boolean isCaptchaRequired(String captchaRedisKey, Integer errCount) {
+        String captchaRedisValue = redisUtil.getCacheObject(captchaRedisKey);
+        if (captchaRedisValue == null && Convert.toInt(captchaRedisValue) > errCount) {
+            return false;
+        }
+        return true;
+    }
+
     /**
      * 校验 验证码
      */

+ 1 - 1
src/main/java/com/backendsys/modules/system/entity/SysAuth.java

@@ -18,7 +18,7 @@ public class SysAuth {
     @NotEmpty(message="密码不能为空", groups = { Login.class, Register.class })
     private String password;
 
-    @NotEmpty(message="验证码不能为空", groups = { Login.class, Register.class })
+    // @NotEmpty(message="验证码不能为空", groups = { Login.class, Register.class })
     private String captcha;
 
     private Integer is_remember;

+ 22 - 6
src/main/java/com/backendsys/modules/system/service/impl/SysAuthServiceImpl.java

@@ -3,6 +3,7 @@ package com.backendsys.modules.system.service.impl;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.backendsys.exception.CustException;
 import com.backendsys.modules.common.config.redis.utils.RedisUtil;
@@ -77,8 +78,7 @@ public class SysAuthServiceImpl implements SysAuthService {
     private String redisKeyOfRegister = APPLICATION_NAME + "-sms-register";
     private String redisKeyOfLoginFail = APPLICATION_NAME + "-login-error";
     private String redisKeyOfRegisterFail = APPLICATION_NAME + "-register-error";
-    
-    
+    private String redisKeyOfCaptchaRequired = APPLICATION_NAME + "-" + httpRequestUtil.getKaptchaKey() + "-required";
 
     @Override
     public void renderCaptcha(HttpServletResponse response) throws IOException {
@@ -115,6 +115,13 @@ public class SysAuthServiceImpl implements SysAuthService {
 
     // [方法] 登录失败 (errMsg: 错误提示文本, username: 用户名, intercept: 是否拦截)
     private void loginFail(String errMsg, String username, Boolean isIntercept) {
+
+        // 输入错误时,计数器叠加,并且设置重置时间 (会一直叠加)
+        Integer currentErrCount;
+        Object captchaRequired = redisUtil.getCacheObject(redisKeyOfCaptchaRequired);
+        currentErrCount = (captchaRequired == null) ? 1 : (Convert.toInt(captchaRequired) + 1);
+        redisUtil.setCacheObject(redisKeyOfCaptchaRequired, currentErrCount, 1, TimeUnit.MINUTES);
+
         // 删除图形验证码
         redisUtil.delete(httpRequestUtil.getKaptchaKey());
         // 添加登录错误的冻结标记
@@ -197,10 +204,19 @@ public class SysAuthServiceImpl implements SysAuthService {
         // 判断是否处于登录错误的冻结状态 (2分钟内错误5次,则出现冻结提示)
         lockStatusUtil.checkLockStatus(redisKeyOfLoginFail, username);
 
-        // 判断图形验证码是否正确
-        if (!captchaUtil.isCaptchaValid(captcha, httpRequestUtil.getKaptchaKey())) {
-            loginFail("验证码错误", username, false);
-            return null;
+        // 判断是否需要输入验证码
+        // - 当输错 3 次密码时,需要输入验证码
+        // - 当输错后 1 分钟后重置
+        Boolean isCaptchaRequired = captchaUtil.isCaptchaRequired(redisKeyOfCaptchaRequired, 3);
+        if (isCaptchaRequired) {
+            if (StrUtil.isEmpty(captcha)) {
+                loginFail("验证码不能为空", username, false);
+                return null;
+            }
+            if (!captchaUtil.isCaptchaValid(captcha, httpRequestUtil.getKaptchaKey())) {
+                loginFail("验证码错误", username, false);
+                return null;
+            }
         }
 
         // [Method] 判断 用户 是否存在 && 密码是否正确