7.0 KiB
7.0 KiB
后端限流配置修复说明
🐛 问题描述
现象: 第一次点击登录就提示"登录过于频繁,请1秒后再试"
错误信息:
{
"code": 500,
"message": "登录过于频繁,请1秒后再试",
"data": null
}
🔍 问题原因
原始配置
在 AuthController.java 第42行:
@RateLimit(limitType = RateLimit.LimitType.IP, permitsPerSecond = 1, message = "登录过于频繁,请1秒后再试")
问题分析
- 限流太严格:
permitsPerSecond = 1表示每秒只允许1次请求 - Guava RateLimiter 特性: 使用令牌桶算法,第一次请求会立即消耗令牌
- IP 限流: 基于 IP 地址限流,本地开发时所有请求都是同一个 IP
- 缓存问题:
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 热部署
- 在 IDEA 中修改代码
- 点击 "Build" → "Rebuild Project"
- 等待自动重启
方法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 = "登录过于频繁,请稍后再试")
配置原则
- 登录类接口: 3-5次/秒,平衡安全和体验
- 注册类接口: 1次/秒,防止批量注册
- 验证码接口: 1次/分钟,防止短信轰炸
- 业务接口: 根据实际情况调整
⚠️ 注意事项
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
状态: ✅ 已修改,待重启服务