From da0f6d4998e278c3bcf025a2e1af1ba469eea100 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 26 八月 2026 11:37:11 +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