From ecad3666fe64603a5aa3994a360f440758664b9f Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 26 八月 2026 13:50:01 +0800
Subject: [PATCH] 增加管理后台登录频次校验和连续错误登录后限制登录 修改管理后台验证码生成和登录校验

---
 ruoyi-auth/src/main/java/com/ruoyi/auth/service/LoginRateLimitService.java |   43 ++++++++++++++++++-------------------------
 1 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/LoginRateLimitService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/LoginRateLimitService.java
index 27ff41a..9fedad0 100644
--- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/LoginRateLimitService.java
+++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/LoginRateLimitService.java
@@ -6,41 +6,45 @@
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
-import javax.servlet.http.HttpServletRequest;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import com.ruoyi.common.core.constant.CacheConstants;
 import com.ruoyi.common.core.exception.ServiceException;
 import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.core.utils.ip.IpUtils;
 import com.ruoyi.common.redis.service.RedisService;
 
 /**
- * 登录频率限制服务
+ * 登录频率限制服务(账号维度)
  */
 @Component
 public class LoginRateLimitService
 {
-    private static final String UNKNOWN = "unknown";
-    private static final String SESSION_HEADER = "X-Login-Session";
-
     @Autowired
     private RedisService redisService;
 
     /**
-     * 按 IP、账号、登录会话三个维度限制登录尝试频率。
+     * 按账号维度限制登录尝试频率。
+     * IP、登录会话维度已由网关 LoginRateLimitFilter 在验证码校验之前处理
+     * (验证码错误的请求不会到达本服务,若在 auth 重复计数会与网关双重计数)。
      */
-    public void checkLoginRate(String username, HttpServletRequest request)
+    public void checkLoginRate(String username)
     {
         String normalizedUsername = StringUtils.defaultString(username).trim().toLowerCase(Locale.ROOT);
-        String ip = StringUtils.defaultIfEmpty(IpUtils.getIpAddr(request), UNKNOWN);
-        String sessionId = resolveSessionId(request);
-
-        checkDimension("ip", ip);
         checkDimension("account", normalizedUsername);
-        checkDimension("session", sessionId);
+    }
+
+    /**
+     * 清除账号维度的登录限流计数(登录成功后调用)。
+     */
+    public void clearAccountRecord(String username)
+    {
+        String normalizedUsername = StringUtils.defaultString(username).trim().toLowerCase(Locale.ROOT);
+        String key = CacheConstants.LOGIN_RATE_LIMIT_KEY + "account:" + digest(normalizedUsername);
+        if (redisService.hasKey(key))
+        {
+            redisService.deleteObject(key);
+        }
     }
 
     private void checkDimension(String dimension, String identity)
@@ -53,17 +57,6 @@
             long retryAfter = remainingSeconds > 0 ? remainingSeconds : CacheConstants.LOGIN_RATE_LIMIT_WINDOW;
             throw new ServiceException(String.format("登录尝试过于频繁,请%s秒后重试", retryAfter));
         }
-    }
-
-    private String resolveSessionId(HttpServletRequest request)
-    {
-        String sessionId = request.getHeader(SESSION_HEADER);
-        if (StringUtils.isNotEmpty(sessionId))
-        {
-            return sessionId;
-        }
-        String userAgent = StringUtils.defaultString(request.getHeader("User-Agent"));
-        return IpUtils.getIpAddr(request) + "|" + userAgent;
     }
 
     private String digest(String value)

--
Gitblit v1.7.1