光靠认证远远不够,必须在路由层+请求处理链路中叠加速率限制、行为特征过滤和令牌生命周期管控;symfony ratelimiter可在防火墙后控制器前拦截超额请求,支持多维策略;需识别异常ua、路径遍历、毫秒级高频请求;jwt须设exp≤15分钟、校验jti防重放;token仅从authorization头提取。

直接上结论:光靠认证(比如 Bearer 令牌)远远不够,必须在路由层+请求处理链路中叠加速率限制、行为特征过滤和令牌生命周期管控。否则恶意脚本只要拿到一个有效 token,就能无限刷接口。
用 Symfony RateLimiter 组件做路由级限流
这是最便宜、最有效的第一道防线。别依赖 Nginx 或外部中间件——Symfony 8.1+ 的 RateLimiter 可以在安全防火墙之后、控制器之前就拦截超额请求,且支持按 IP、用户 ID、路由名等多维度策略。
- 配置示例(
config/packages/security.yaml):
security:
# ...
firewalls:
api:
rate_limiter: 'api_limit'
framework:
rate_limiter:
api_limit:
policy: 'token_bucket'
limit: 60
interval: '1 minute'
# 可选:用 user identifier 替代 IP,防止同一用户多设备绕过
# key: '%request.attributes.get("user")?.getUserIdentifier() ?: request.client_ip'
-
token_bucket比fixed_window更抗突发流量,适合 API 场景 - 如果用
key基于用户标识,需确保UserInterface::getUserIdentifier()返回稳定值(如数据库 ID),不能是 email 或 username(可能被撞库) - 注意:
rate_limiter在Firewall阶段生效,未通过认证的请求默认不计入限流(除非你显式启用anonymous策略)
识别并拦截低质量请求(User-Agent、路径遍历、时间规律)
单纯限流挡不住伪装成浏览器的爬虫。你需要在控制器前加一层轻量级行为分析,不依赖 AI 模型,只靠几个硬指标筛出异常请求。
- 典型异常信号:
• User-Agent 为空、含 curl/、python-requests、或重复出现非主流 UA 字符串
• 请求路径为 /api/v1/users/{id} 却连续递增 {id}(遍历攻击)
• 同一 IP 在 100ms 内发起 5+ 次不同路径请求(毫秒级节奏 = 脚本)
- 实现建议:写一个
RequestInterceptorInterface(Symfony 8.1+),在handle()中检查$request->headers->get('User-Agent')和$request->getRequestUri()模式,匹配即抛出TooManyRequestsHttpException - 不要在这里做复杂正则或 DB 查询——拦截必须在毫秒级完成,否则拖慢所有合法请求
令牌必须带短时效 + 可吊销,且拒绝重放
很多团队用 JWT 但忽略两个致命点:一是签发长期 token(如 7 天),二是不校验 jti(JWT ID)防重放。一旦 token 泄露,攻击者可永久刷接口。
- 强制设置
exp≤ 15 分钟,并搭配 refresh token 流程(refresh token 存 DB,每次使用后失效) - 在
OidcTokenHandler::getUserBadgeFrom()中增加jti去重检查:
→ 查 DB 是否已存在该jti(已用过即拒绝)
→ 成功验证后立即插入该jti(哪怕只存 Redis 5 分钟也比不存强) - 禁止从查询参数(
?token=xxx)传 token——它会进 access log、CDN 缓存、浏览器历史,等于公开 token - 所有 token 提取必须走
HeaderAccessTokenExtractor,即只认Authorization: Bearer xxx
最容易被忽略的其实是「限流与认证的顺序」:如果你把限流放在自定义认证逻辑之后,而认证本身要查 DB 或调 OAuth2 服务器,那攻击者只要高频发无效 token,就能把你的认证服务打挂——限流必须卡在更早的阶段,比如 Firewall 或 RequestInterceptor。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











