主要变更: 1. 所有 Entity/DTO/VO 添加 @Schema 注解,完善 API 文档 2. 新增前端 API 封装模块 (src/apis),包含 fetch.ts 和 apis.ts 3. 生成完整的 TypeScript 类型定义(100+ 个模型) 4. pom.xml 添加 Maven 编译配置和 UTF-8 编码支持 5. 更新 CLAUDE.md 开发文档,新增接口规范和 Swagger 注解规范 6. 清理旧的文档文件和 Flyway 迁移脚本 技术细节: - 后端:27 个实体类 + 所有 DTO/Response 添加 Swagger 注解 - 前端:新增 orval 生成的 API 客户端类型 - 构建:配置 Maven compiler plugin 和 Spring Boot 插件的 JVM 参数 - 数据库:新增 schema 导出文件,删除旧 Flyway 迁移脚本 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6.4 KiB
6.4 KiB
限流功能使用说明
功能概述
本项目已集成基于 Redis 滑动窗口算法的限流功能,支持两种使用方式:
- 配置化限流 - 在
application.yml中配置规则,自动对所有接口生效 - 注解限流 - 在 Controller 方法上使用
@RateLimit注解,针对特定接口限流
技术实现
核心组件
| 组件 | 说明 |
|---|---|
@RateLimit |
限流注解,可自定义时间窗口、最大请求数 |
RateLimitProperties |
配置化限流的属性类 |
RateLimiter |
Redis 限流工具类(滑动窗口算法) |
RateLimitAspect |
注解限流的 AOP 切面 |
RateLimitInterceptor |
配置化限流的拦截器 |
ErrorCode.RATE_LIMIT_EXCEEDED |
限流错误码(5001) |
限流优先级
注解限流 > 配置化限流 > 默认限流
使用方式
方式一:配置化限流(推荐作为基础防护)
在 application.yml 中配置:
rate-limit:
enabled: true # 是否启用限流
default-time-window: 60 # 默认时间窗口(秒)
default-max-requests: 1000 # 默认时间窗口内最大请求数
rules: # 限流规则列表
# 登录接口限流 - 防止暴力破解
- pattern: "/api/v1/auth/login"
time-window: 60
max-requests: 10
# 验证码接口限流 - 防止刷验证码
- pattern: "/api/v1/auth/captcha"
time-window: 60
max-requests: 5
# 短信接口限流 - 防止短信轰炸
- pattern: "/api/v1/sms/**"
time-window: 60
max-requests: 3
# 文件上传接口限流
- pattern: "/api/v1/**/upload/**"
time-window: 60
max-requests: 30
exclude-patterns: # 排除限流的接口
- "/doc.html"
- "/swagger-resources/**"
- "/v3/api-docs/**"
- "/webjars/**"
- "/uploads/**"
方式二:注解限流(针对特殊接口)
在 Controller 方法上添加 @RateLimit 注解:
package com.reading.platform.controller.auth;
import com.reading.platform.common.annotation.RateLimit;
import com.reading.platform.common.response.Result;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {
/**
* 登录接口 - 限流防止暴力破解
* 60 秒内最多 10 次请求
*/
@PostMapping("/login")
@RateLimit(time = 60, maxRequests = 10, message = "登录过于频繁,请稍后再试")
public Result<LoginResponse> login(@RequestBody LoginRequest request) {
// ... 登录逻辑
}
/**
* 发送短信验证码 - 严格限流
* 60 秒内最多 3 次请求
*/
@PostMapping("/captcha")
@RateLimit(time = 60, maxRequests = 3, message = "操作过于频繁,请稍后再试")
public Result<Void> sendCaptcha(@RequestParam String phone) {
// ... 发送验证码逻辑
}
/**
* 自定义限流键前缀
* 适用于需要按用户 ID 等特殊维度限流的场景
*/
@PostMapping("/special")
@RateLimit(keyPrefix = "special_api:", time = 60, maxRequests = 5)
public Result<Void> specialApi() {
// ... 特殊接口逻辑
}
}
常见限流场景建议值
| 接口类型 | 时间窗口 | 最大请求数 | 说明 |
|---|---|---|---|
| 登录接口 | 60 秒 | 10 | 防止暴力破解 |
| 验证码/短信 | 60 秒 | 3-5 | 防止短信轰炸 |
| 文件上传 | 60 秒 | 30 | 防止资源滥用 |
| 普通业务接口 | 60 秒 | 100-1000 | 根据业务调整 |
| 导出接口 | 60 秒 | 5-10 | 防止服务器过载 |
限流响应
当请求被限流拦截时,返回:
配置化限流响应:
{
"code": 5001,
"message": "请求过于频繁,请稍后再试",
"data": null
}
HTTP 状态码:429 Too Many Requests
响应头:
X-RateLimit-Limit: 1
X-RateLimit-Remaining: 0
Retry-After: 60
注解限流响应:
{
"code": 5001,
"message": "登录过于频繁,请稍后再试",
"data": null
}
Redis 数据结构
限流使用 Redis 的 Sorted Set(有序集合)存储:
- Key 格式:
rate_limit:{key} - Member: 时间戳(毫秒)
- Score: 时间戳(毫秒)
示例:
rate_limit:192.168.1.1:/api/v1/auth/login
|- 1710000000000
|- 1710000001000
|- 1710000002000
注意事项
- Redis 依赖: 限流功能依赖 Redis,需确保 Redis 服务可用
- 异常情况放行: 当 Redis 不可用时,系统会自动放行请求,避免影响正常业务
- 集群部署: 滑动窗口算法天然支持分布式,无需额外配置
- 监控告警: 建议添加限流触发的监控告警,及时发现异常流量
日志示例
2024-03-10 22:00:00 WARN - 请求被限流拦截:URI=/api/v1/auth/login, 规则=/api/v1/auth/login, 最大请求数=10
2024-03-10 22:00:01 DEBUG - 请求通过限流检查:URI=/api/v1/users, 规则=default
测试方法
使用 curl 或 Postman 快速测试:
# 循环发送 15 次登录请求(第 11 次开始应该被限流)
for i in {1..15}; do
echo "请求 $i:"
curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test"}' \
-w "\nHTTP 状态码:%{http_code}\n\n"
done
配置说明
RateLimit 注解参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
keyPrefix |
String | "" | 限流键前缀,默认使用 IP:类名。方法名 |
time |
long | 60 | 时间窗口大小 |
timeUnit |
TimeUnit | SECONDS | 时间单位 |
maxRequests |
long | 100 | 时间窗口内最大请求数 |
message |
String | "请求过于频繁,请稍后再试" | 限流提示信息 |
enabled |
boolean | true | 是否启用限流 |
application.yml 配置参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
boolean | true | 是否启用限流 |
default-time-window |
long | 60 | 默认时间窗口(秒) |
default-max-requests |
long | 1000 | 默认最大请求数 |
rules |
List | [] | 限流规则列表 |
exclude-patterns |
List | [] | 排除限流的接口路径 |
RateLimitRule 配置参数
| 参数 | 类型 | 说明 |
|---|---|---|
pattern |
String | 接口路径(支持 Ant 风格通配符) |
time-window |
long | 时间窗口(秒) |
max-requests |
long | 最大请求数 |