spring boot 通过“时间戳+nonce+签名”三要素防重放攻击:时间戳校验±5分钟偏差,nonce用redis确保一次性,签名基于hmac-sha256对标准化参数验签;建议用@aop或拦截器统一管控。

Spring Boot 为 REST 接口实现基于签名的时间戳防重放攻击校验,核心是构建“时间戳 + 随机数(Nonce)+ 签名(Signature)”三要素协同验证机制。单靠时间戳只能防过期请求,必须配合 Nonce 和签名,才能真正拦截窗口期内的重复请求和参数篡改。
时间戳校验:划定请求有效时间窗口
客户端在请求头或参数中携带当前毫秒级时间戳(如 timestamp=1752681000000)。服务端收到后立即比对系统时间:
- 允许偏差通常设为 ±5 分钟(300000 毫秒),超出即拒绝
- 不建议用秒级时间戳,毫秒级能更好对抗快速重放
- 服务端必须使用系统真实时间(禁用客户端传来的时区或格式化时间)
Nonce 校验:确保请求一次性生效
客户端每次请求生成唯一随机字符串(如 UUID 或 16 位 Base62 字符串),通过 nonce 参数或 Header 传递。服务端需做两件事:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 检查该 Nonce 在 Redis 中是否已存在(Key 可设为 nonce:{value})
- 若不存在,则写入并设置过期时间(如 300 秒),与时间戳窗口对齐
- 若已存在,直接返回 401 或自定义错误码,不进入业务逻辑
签名生成与验证:保障参数完整性
签名不是对整个 Body 加密,而是对标准化后的参数集合进行 HMAC-SHA256 计算:
- 提取所有非签名相关参数(排除 sign、signature、timestamp、nonce 等)
- 参数按字典序升序排列,拼接为 key1=value1&key2=value2&… 格式
- 追加 timestamp 和 nonce 字段(如 ×tamp=1752681000000&nonce=abc123)
- 用双方约定的 AppSecret 作为密钥,执行 HMAC-SHA256,结果转为小写十六进制字符串
- 服务端用同样规则重新计算,比对客户端传来的 sign 值是否一致
落地建议:用拦截器 + AOP 统一管控
避免在每个 Controller 方法里重复写校验逻辑:
- 定义一个 @ApiSignature 注解,支持配置超时时间、appId 参数名等
- 用 Spring AOP 或 HandlerInterceptor 拦截带该注解的方法
- 拦截器中统一完成:解析参数 → 校验 timestamp → 查询/存入 Redis 的 Nonce → 重组参数并验签
- 校验失败抛出全局异常(如 SignatureException),由 @ControllerAdvice 统一返回 JSON 错误响应










