抗重放机制需在所有身份验证接口强制启用“时间戳+随机数+签名”三要素联动校验:x-auth-timestamp(误差≤300秒)、x-auth-nonce(uuid v4且不可复用)、x-auth-signature(hmac-sha256签名,含完整请求体),缺一返回400;服务端按签名→时间戳→nonce顺序校验,nonce用redis原子操作防重放。

直接在所有身份验证接口上启用抗重放机制,核心是“时间戳 + 随机数 + 签名”三要素联动校验,缺一不可。单靠时间窗口或单靠 nonce 都存在明显短板,组合使用才能覆盖攻击窗口期与并发重复场景。
强制携带三要素请求头
所有身份验证接口(如登录、换 token、绑定手机号等)必须要求客户端在 HTTP 请求头中提供以下三项:
-
X-Auth-Timestamp:毫秒级 UNIX 时间戳,服务端用
System.currentTimeMillis()或time.time_ns() // 1_000_000校验,误差容忍 ≤ 300 秒(5 分钟); -
X-Auth-Nonce:UUID v4 生成的 32 位小写字符串(如
550e8400-e29b-41d4-a716-446655440000),禁止复用; -
X-Auth-Signature:对
body + timestamp + nonce拼接后,用 HMAC-SHA256 和平台密钥生成的十六进制签名,大小写敏感。
不带全三项的请求,直接返回 400 Bad Request,不进入业务逻辑。
服务端按顺序执行三重校验
拦截器或全局过滤器中,必须严格按以下顺序校验,任一失败立即中断:
- 先校验签名有效性:提取原始请求体(需缓存读取)、timestamp、nonce,按相同规则拼接并重算 HMAC,用
hmac.compare_digest防侧信道攻击; - 再验证时间戳:计算
abs(now - timestamp),超 300 秒即拒,同时拒绝未来时间戳超过 10 秒的请求(防客户端时钟严重超前); - 最后查 nonce 是否已存在:用 Redis 的
SET key value EX 300 NX原子操作,成功写入表示首次使用,失败则说明已被消费,返回403 Forbidden。
Redis key 建议设为 auth:nonce:{md5(nonce)},避免长字符串作 key 影响性能;过期时间设为 300 秒,与时间窗口一致。
密钥与签名范围的实操要点
签名不能只签参数,必须包含可变上下文:
- 签名原文必须含完整请求体(JSON 字符串,保留空格与顺序),禁用 query string 参数参与签名(易被代理篡改);
- 密钥建议按应用维度隔离(如
app_key=abc123对应密钥sk_abc123_v2),避免一处泄露全盘失守; - 若接口支持多租户,签名原文中需加入
tenant_id字段,防止跨租户重放; - 敏感操作(如修改密码、解绑设备)额外叠加
device_fingerprint或ip_hash到签名原文中,提升绑定强度。
配套运维与降级策略
机制上线后需同步落地支撑措施:
- 所有客户端 SDK 必须内置时间自动校准逻辑(如定期调用
/api/time获取服务端时间,修正本地偏差); - Redis 缓存 nonce 的内存用量需监控,当日峰值 key 数超 100 万时触发告警,避免爆内存;
- 灰度期开启双校验日志:记录每笔请求的 timestamp 差值、nonce 冲突次数、签名耗时,用于定位误杀;
- 紧急情况下可通过配置中心动态关闭 nonce 校验(保留 timestamp+signature),但需同步提升时间窗口至 60 秒并加强风控审计。











