发布于2026-04-21 阅读(0)
扫一扫,手机访问

本文介绍如何在 Spring Boot 应用中基于用户维度(而非全局)实现精准的请求速率限制,通过唯一用户标识(如 username + sessionId)结合缓存机制,确保各用户独立计数、互不干扰。
本文介绍如何在 Spring Boot 应用中基于用户维度(而非全局)实现精准的请求速率限制,通过唯一用户标识(如 username + sessionId)结合缓存机制,确保各用户独立计数、互不干扰。
在典型的 Spring Boot 项目中,全局速率限制(例如使用 @RateLimiter 或自定义 Filter 限制每分钟 5 次请求)会将所有请求统一计数,导致“用户 A 触发限流后,用户 B 也被阻塞”——这显然违背了多租户或个性化风控场景的需求。要实现按用户隔离的速率控制,核心在于:为每个用户生成唯一且稳定的限流键(rate-limit key),并基于该键进行独立计数与校验。
构造用户级限流键:推荐组合 username(需认证后获取)与 sessionId(增强会话粒度),例如:
String userKey = String.format("rate_limit:%s:%s", username, sessionId);⚠️ 注意:若使用 JWT 无状态认证,可用 userId 或 subject 替代 sessionId,确保键具备唯一性与可追溯性。
选择高性能存储计数器:
集成到请求处理链路:
通常通过 HandlerInterceptor 或 Filter 在请求进入 Controller 前完成校验:
@Component
public class UserRateLimitInterceptor implements HandlerInterceptor {
private final RedisTemplate<String, Object> redisTemplate;
private static final String RATE_LIMIT_KEY_PREFIX = "user:rl:";
private static final long WINDOW_SECONDS = 60L;
private static final int MAX_REQUESTS_PER_WINDOW = 5;
public UserRateLimitInterceptor(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 1. 获取当前用户标识(示例:从 SecurityContext 获取)
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPrincipal() == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().write("Unauthorized");
return false;
}
String username = auth.getName();
String sessionId = request.getSession().getId();
// 2. 构建用户专属限流键
String key = RATE_LIMIT_KEY_PREFIX + username + ":" + sessionId;
// 3. 使用 Redis 原子递增并设置过期(首次访问自动设 TTL)
Long count = redisTemplate.opsForValue().increment(key, 1);
if (count == 1) {
redisTemplate.expire(key, WINDOW_SECONDS, TimeUnit.SECONDS);
}
// 4. 校验是否超限
if (count > MAX_REQUESTS_PER_WINDOW) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.setContentType("application/json");
response.getWriter().write("{\"error\":\"Rate limit exceeded for this user\"}");
return false;
}
return true;
}
}通过以上方案,每个用户都将拥有独立的计数器,真正实现“用户 A 被限流,不影响用户 B”的精细化管控能力,既保障系统稳定性,又兼顾用户体验与业务灵活性。
上一篇:客户管理联系提醒天数怎么设置
下一篇:Edge浏览器如何恢复上次网页?
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8