https仅保障传输层加密,不验证应用层数据完整性;签名需包含method、path、timestamp等字段,缺一则防篡改或防重放失效。

Python开发的API接口不做参数签名,等于把请求的“身份证”和“封条”都扔在路边——HTTPS只保传输不保内容,攻击者截包后改个amount=1变成amount=999999,服务端照单全收。
为什么HTTPS不够用
HTTPS加密的是TCP层到TLS层之间的字节流,但一旦请求到达服务端,request.args和request.get_json()拿到的就是明文。中间人若已控制客户端设备(比如恶意App、被劫持的Wi-Fi)、或通过XSS/恶意插件拿到请求体,就能任意构造合法TLS连接下的篡改请求。签名验证是在应用层做“内容指纹”,和HTTPS是两道独立防线。
HMAC-SHA256签名必须包含哪些字段
漏掉任何一个,防篡改或防重放就形同虚设:
-
method:GET/POST/PUT等,防止把查询接口当修改接口用 -
path:完整路径(不含域名和query),避免/user被替换成/admin/user -
timestamp:秒级UNIX时间戳,服务端校验abs(now - timestamp) -
nonce:一次性的随机字符串,Redis中SETEX nonce 300 "1"存5分钟 -
sorted_query_string:query参数按key字典序拼成a=1&b=2,URL编码值 -
body_bytes:仅对application/json取原始request.get_data(cache=True),空body也要参与签名
签名原文拼接时最容易错的三处
不是“把参数连起来hash一下”那么简单:
- 换行符必须是
\n(不是\r\n或空格),否则服务端重算结果必然不一致 -
body_bytes如果存在,必须用原始字节解码为UTF-8字符串再拼;直接str(request.get_data())会带b'...'前缀 - query参数排序前要过滤掉
signature、timestamp、nonce等签名元数据,否则客户端和服务端排序结果不一致
Flask里验签装饰器的性能陷阱
看似简单的一行hmac.new(...).hexdigest(),实际瓶颈不在计算本身,而在三处:
- 重复读
request.get_data():不加cache=True会导致body被多次读空,后续视图函数拿不到数据 - Redis查
nonce失败没设超时:网络抖动时阻塞整个请求,建议r.exists(nonce, socket_timeout=0.1) - 没跳过
OPTIONS预检:浏览器自动发的预检请求没X-Signature头,直接401会中断CORS流程
真正难的不是写对那几行hmac.new,而是让签名逻辑在高并发下不拖慢正常请求、不因缓存失效导致误拒、也不因大小写/空格/编码差异让前后端算出两个签名。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











