peixue-dev/peidu/后端限流配置修复说明.md

7.0 KiB
Raw Blame History

后端限流配置修复说明

🐛 问题描述

现象: 第一次点击登录就提示"登录过于频繁请1秒后再试"

错误信息:

{
  "code": 500,
  "message": "登录过于频繁请1秒后再试",
  "data": null
}

🔍 问题原因

原始配置

AuthController.java 第42行

@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 1, message = "登录过于频繁请1秒后再试")

问题分析

  1. 限流太严格: permitsPerSecond = 1 表示每秒只允许1次请求
  2. Guava RateLimiter 特性: 使用令牌桶算法,第一次请求会立即消耗令牌
  3. IP 限流: 基于 IP 地址限流,本地开发时所有请求都是同一个 IP
  4. 缓存问题: RateLimiter 实例被缓存,重启前的限流状态会保留

解决方案

1. 调整限流配置

修改前:

@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 1, message = "登录过于频繁请1秒后再试")

修改后:

// 调整限流每秒5次请求避免正常使用时触发限流
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 5, message = "登录过于频繁,请稍后再试")

2. 配置说明

参数 原值 新值 说明
permitsPerSecond 1 5 每秒允许的请求数
message 登录过于频繁请1秒后再试 登录过于频繁,请稍后再试 错误提示

3. 为什么选择 5 次/秒

  • 正常使用: 用户正常点击不会超过5次/秒
  • 防止暴力破解: 仍然能有效防止暴力破解攻击
  • 开发测试: 方便开发和测试
  • 用户体验: 不会影响正常用户体验

📝 修改的文件

backend/src/main/java/com/peidu/controller/AuthController.java

位置: 第42行

修改内容:

// 第42行
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 5, message = "登录过于频繁,请稍后再试")

🔄 如何应用修改

方法1: 重新编译运行(推荐)

# 1. 进入后端目录
cd backend

# 2. 清理并编译
mvn clean package -DskipTests

# 3. 重启后端服务
java -jar target/peidu-backend.jar

方法2: IDEA 热部署

  1. 在 IDEA 中修改代码
  2. 点击 "Build" → "Rebuild Project"
  3. 等待自动重启

方法3: 清除限流缓存

如果不想重启,可以添加一个清除缓存的接口:

@GetMapping("/clear-rate-limit")
public Result<Void> clearRateLimit() {
    rateLimitConfig.cleanExpiredRateLimiters();
    return Result.success();
}

🧪 测试验证

1. 重启后端服务

# 停止当前服务
# Ctrl + C 或 kill 进程

# 重新启动
java -jar target/peidu-backend.jar

2. 测试登录接口

# 使用 curl 测试
curl -X POST http://localhost:8089/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "13800138000",
    "password": "123456"
  }'

3. 预期结果

成功响应:

{
  "code": 200,
  "message": "登录成功",
  "data": {
    "token": "eyJhbGc...",
    "userInfo": {...}
  }
}

限流响应快速连续请求6次以上:

{
  "code": 500,
  "message": "登录过于频繁,请稍后再试",
  "data": null
}

📊 其他接口的限流配置

当前配置一览

接口 限流类型 速率 说明
/api/auth/login IP 5次/秒 已修改
/api/auth/register IP 已禁用 方便测试
/api/auth/send-code IP 1次/分钟 合理
/api/auth/wx-login 无限制 建议添加

建议添加微信登录限流

AuthController.java 的微信登录接口添加:

@ApiOperation("微信登录")
@PostMapping("/wx-login")
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 5, message = "登录过于频繁,请稍后再试")
public Result<Map<String, Object>> wxLogin(@RequestBody WxLoginRequest request) {
    // ...
}

🎯 生产环境建议

推荐配置

// 登录接口每秒3次
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 3, message = "登录过于频繁,请稍后再试")

// 注册接口每秒1次
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 1, message = "注册过于频繁,请稍后再试")

// 发送验证码每分钟1次
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 0.0167, message = "验证码发送过于频繁请1分钟后再试")

// 微信登录每秒3次
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 3, message = "登录过于频繁,请稍后再试")

配置原则

  1. 登录类接口: 3-5次/秒,平衡安全和体验
  2. 注册类接口: 1次/秒,防止批量注册
  3. 验证码接口: 1次/分钟,防止短信轰炸
  4. 业务接口: 根据实际情况调整

⚠️ 注意事项

1. 开发环境 vs 生产环境

开发环境:

  • 可以适当放宽限流
  • 方便测试和调试
  • 建议 5-10次/秒

生产环境:

  • 需要严格限流
  • 防止恶意攻击
  • 建议 1-3次/秒

2. 限流类型选择

IP 限流 (RateLimit.LimitType.IP):

  • 优点:简单有效
  • 缺点:同一 IP 下的所有用户共享限额
  • 适用:登录、注册等公开接口

用户限流 (RateLimit.LimitType.USER):

  • 优点:精确控制每个用户
  • 缺点:需要用户已登录
  • 适用:业务接口、敏感操作

3. 缓存清理

RateLimiter 实例会被缓存,建议:

  • 定期清理过期的限流器
  • 重启服务会清空所有缓存
  • 可以添加管理接口手动清理

🔧 故障排查

问题1: 修改后仍然限流

原因: 缓存未清除
解决: 重启后端服务

问题2: 所有用户都被限流

原因: 使用了 IP 限流,本地开发都是同一 IP
解决:

  • 开发环境放宽限流
  • 或改用用户限流

问题3: 限流配置不生效

原因:

  • 注解位置错误
  • AOP 未生效
  • 依赖未引入

解决:

  • 检查注解是否在正确的方法上
  • 检查 @Aspect 是否生效
  • 检查 Guava 依赖

📚 相关代码

RateLimitAspect.java

限流切面实现,拦截带有 @RateLimit 注解的方法

RateLimitConfig.java

限流配置类,管理 RateLimiter 实例缓存

RateLimit.java

限流注解定义

修改完成清单

  • 修改登录接口限流配置
  • 调整 permitsPerSecond 从 1 到 5
  • 优化错误提示信息
  • 重启后端服务(需要手动执行)
  • 测试验证(需要手动执行)
  • 考虑添加微信登录限流(可选)

🎉 总结

修改后的配置:

  • 不会在第一次请求时就触发限流
  • 仍然能有效防止暴力破解
  • 提供更好的用户体验
  • 方便开发和测试

下一步: 重启后端服务,然后重新测试登录功能!


修改时间: 2026-02-03
修改文件: backend/src/main/java/com/peidu/controller/AuthController.java
状态: 已修改,待重启服务