
1. 为什么API需要防重放攻击想象一下你正在用手机银行转账黑客截获了你的请求数据包。如果没有防护措施他只需要把这个数据包重复发送100次你的账户就会被转空100笔钱——这就是典型的重放攻击Replay Attack。在开放API场景中这种攻击可能导致重复下单造成资金损失恶意刷接口消耗服务器资源数据被篡改引发业务风险去年某电商平台就曾因未做防重放被黑产利用重复调用优惠券接口薅走数百万。要防御这类攻击关键在于让每个请求具备唯一性和时效性这正是Token时间戳随机数组合的用武之地。2. 签名验证的核心三要素2.1 Token身份认证的通行证Token相当于临时身份证它的典型生命周期是这样的# 生成Token示例(Python) import uuid import time def generate_token(user_id): token str(uuid.uuid4()) redis.setex(ftoken:{token}, 3600, user_id) # 1小时过期 return token常见误区是认为有了Token就安全了。实际上单独使用Token存在两大风险中间人攻击网络传输中被截获越权访问低权限Token调用高权限接口2.2 时间戳给请求加上保质期时间戳就像超市商品的保质期标签。我们来看个对比实验时间窗口攻击成功率系统负载无限制100%0%30分钟0.5%0.2%5分钟0.1%1.5%建议时间窗口设为5-15分钟这个区间在安全性和性能间取得较好平衡。处理时间戳时要特别注意// 时间校验错误示范Java if (Math.abs(System.currentTimeMillis() - timestamp) 900000) { throw new Exception(请求过期); } // 正确做法考虑服务器时间同步问题 long maxTimeDiff 900000 30000; // 增加30秒容错2.3 随机数(nonce)一次性密码本nonce的存储策略直接影响系统性能。我们实测了三种方案数据库存储QPS500时可用Redis存储推荐方案设置自动过期内存缓存集群环境下失效这是我们在实际项目中使用的Redis方案def check_nonce(nonce): if redis.exists(fnonce:{nonce}): return False redis.setex(fnonce:{nonce}, 900, 1) # 15分钟过期 return True3. 分布式环境下的实战方案3.1 签名生成五步法以电商下单接口为例完整签名流程如下参数标准化过滤空值参数参数名按ASCII码排序URL编码处理特殊字符构造签名字符串// Node.js示例 const signStr [ method.toUpperCase(), encodeURI(path), sortedParams.join(), timestamp, nonce, token ].join(\n);加密处理推荐HMAC-SHA256算法避免使用MD5等弱哈希签名传输建议放在Authorization头示例Authorization: HMAC-SHA256 keyapp123,signxxxx服务端验证时间窗口检查nonce唯一性校验签名重新计算比对3.2 高并发优化技巧当QPS超过1万时需要特别优化nonce集群同步采用Redis Cluster分片存储批量校验使用Redis管道(pipeline)批量查询缓存签名结果对相同请求缓存验证结果这是我们线上环境的Redis Lua脚本示例-- 原子化校验nonce并记录 local exists redis.call(EXISTS, KEYS[1]) if exists 1 then return 0 else redis.call(SETEX, KEYS[1], ARGV[1], 1) return 1 end4. 防坑指南与性能平衡4.1 常见采坑场景时间不同步所有服务器必须部署NTP服务允许±30秒时间差参数编码问题空格要编码为%20而非中文字符需UTF-8编码签名参数遗漏建议使用白名单机制特别小心文件上传接口4.2 安全与性能的权衡给出三种典型配置方案安全等级签名算法时间窗口nonce存储适用场景基础HMAC-SHA130分钟内存缓存内部系统标准HMAC-SHA25615分钟Redis电商/支付高安全RSA-SHA2565分钟集群同步金融/政务在金融级项目中我们还会增加请求指纹校验// Go语言生成请求指纹 func genFingerprint(r *http.Request) string { h : sha256.New() h.Write([]byte(r.RemoteAddr)) h.Write([]byte(r.UserAgent())) return base64.StdEncoding.EncodeToString(h.Sum(nil)) }5. 全链路防护体系完整的API安全需要多层防护传输层强制HTTPS证书绑定认证层Token动态签名业务层频率限制行为分析监控层实时异常检测某银行系统的实际部署架构客户端 - WAF防火墙 - API网关 - 签名验证 - 业务逻辑 ↑ ↑ 流量清洗 动态令牌服务最近帮一个客户做安全审计时发现他们虽然实现了签名验证但在文件上传接口漏掉了文件内容的签名校验导致攻击者可以替换上传的文件内容。这个问题教会我们安全方案必须覆盖所有接口类型。