HTTP头与Body签名怎么做?,签名算法有哪些?
- 前端开发
- 2026-08-13
- 7
HTTP Header签名和HTTP Body签名是API安全中用于验证请求完整性和身份的两大核心机制,二者分别保护请求头和请求体,结合使用能有效防止数据改动和重放攻破。任何面向公网的API,只要涉及敏感操作或数据交换,签名机制几乎成为标配,你不必理解全部密码学细节,但必须掌握它们的协作逻辑和常见落地方式,否则调试接口时可能反复栽在“签名验证失败”上。
什么是HTTP Header签名和HTTP Body签名?
这两个概念经常一起出现,但作用对象不同,Header签名锁定请求头中的关键字段,Body签名锁定请求体内容。
HTTP Header签名
它是对请求头中特定字段(如Date、Host、Content-Type、X-Custom-Header等)进行签名,签名值通常放在Authorization头中,或者单独的自定义头里,服务端收到请求后,会重新计算这些头的签名,比对是否一致,如果中间人改动了Date或Host,签名就会失效,常见于AWS Signature V4、阿里云RPC签名等。
HTTP Body签名
它是对请求体(Payload)进行哈希,然后将哈希值作为签名的一部分,服务端接收到请求体后,会重新计算哈希,与签名中的哈希比对,如果请求体在传输过程中被修改,哪怕一个字节,哈希值也会变化,导致签名验证失败,这对POST、PUT、PATCH等带请求体的方法尤其重要。
二者如何协同工作
完整的签名过程通常是:客户端先对Body计算哈希,然后提取关键Header,将Body哈希也视为一个“虚拟Header”,一起参与签名计算,最终生成的签名同时绑定了Header和Body,服务端反向验证,确保两者都未被改动。
HTTP Header签名 vs Body签名:应用场景与选择
并不是所有场景都需要同时签Header和Body,你需要根据接口的敏感程度和风险模型来决定。
只签Header的场景
某些只读接口或GET请求,没有请求体,只需签名Header即可,此时主要防止URL参数被改动,以及通过时间戳防止重放,例如公共资源查询接口,仅验证调用方身份。
必须签Body的场景
任何涉及数据提交的接口,如支付、订单创建、用户信息修改,都应包含Body签名,因为请求体一旦被改动,后果严重,多数云厂商的API签名规范,都要求对Body进行哈希后参与签名。
联合签名的常见做法
提取必要Header:Date、Host、Content-Type、X-Content-Sha256(自定义Header,存储Body哈希值)。
计算Body哈希:使用SHA256算法对请求体字节计算摘要。
构造待签名字符串:包含HTTP方法、URI、查询参数、Header列表、Body哈希值。
使用HMAC-SHA256等算法,用AccessKey Secret对字符串签名。
将签名值放入Authorization头,并附带Body哈希、签名时间戳等信息。
服务端完全复制这个过程,比对签名结果。
如何实现HTTP Header签名和Body签名
下面以对接主流云厂商API为例,拆解实操步骤,虽然各家细节有差异,核心逻辑一致。
签名算法选择
行业共识认为,HMAC-SHA256是目前最平衡安全与性能的选择,部分历史接口仍用HMAC-SHA1,但建议新项目统一使用SHA256。
签名步骤示例(伪代码)
准备请求:假设为POST请求,Body为JSON字符串,Header包含Date、Host、Content-Type。
2. 计算Body哈希:`body_hash = SHA256(body_json)`
3. 构造待签名字符串:
`StringToSign = HTTPMethod + “n” + URI + “n” + QueryString + “n” + Headers(排序拼接) + “n” + body_hash`
4. 计算签名:`signature = HMAC-SHA256(SecretKey, StringToSign)`
5. 添加Header:`Authorization: HMAC-SHA256 AccessKey=xxx, Signature=signature, SignedHeaders=host;date;content-type`
同时将`X-Content-Sha256: body_hash`放入Header。

验证签名时服务端操作
从Authorization头中提取SignedHeaders列表。
按相同顺序拼接这些Header的值。
从X-Content-Sha256头中读取客户端的Body哈希。
重新计算接收到的Body的SHA256,与客户端哈希比对。
重新构造待签名字符串,使用存储的SecretKey计算签名,与客户端签名比对。
常见实现语言
Python、Java、Go、Node.js均有SDK封装签名逻辑,但仍建议理解底层原理,以便排查问题,如果使用SDK,注意版本更新,部分旧版SDK可能未强制校验Body哈希。
签名验证失败的常见原因与排查方法
这是开发者最常遇到的痛点,签名验证失败时,接口会返回403或401错误,提示“SignatureDoesNotMatch”,你需要按以下步骤逐一排查。
时钟偏差导致签名过期
签名中通常包含时间戳,服务端验证时间差是否在15分钟内,如果服务器时间相差超过5分钟,签名直接失效。解决方案:同步NTP服务,确保客户端与服务器时间误差在1分钟内。
Body哈希不匹配
这是最常见的原因,客户端计算Body哈希时,可能对请求体进行了编码转换(如UTF-8),但服务端使用了不同的编码;或者Body被压缩后未重新计算哈希。检查点:确认客户端和服务端读取的是完全相同的字节流。
Header顺序或缺失
签名要求对Header列表按字典序排序,并拼接成特定格式,如果遗漏了某个Header,或者排序方式不一致,签名串就会不同。排查方法:在客户端打印出待签名字符串,在服务端模拟打印,逐字符对比。

查询参数未参与签名
部分签名规范要求URI中的Query参数也参与签名,如果参数顺序变化或参数值被URL编码,签名也会失败。建议:严格按照规范文档对参数进行排序和编码。
第一步:检查服务端错误日志,确认具体的签名错误项。
第二步:对比客户端和服务端的待签名字符串,使用工具如在线字符串对比。
第三步:确认算法一致,包括哈希算法和HMAC算法。
第四步:检查AccessKey和SecretKey是否匹配,是否存在密钥过期。
第五步:使用抓包工具(如Wireshark、Fiddler)捕获原始请求,确认Body是否被中间件改动。
HTTP签名工具推荐与使用技巧
调试签名时,手动计算容易出错,借助工具能大幅提升效率。
在线签名生成工具
部分云厂商提供在线签名调试页面,输入参数即可生成签名,但注意:不要在不可信网站上输入真实SecretKey,建议使用测试密钥,工具仅用于验证算法逻辑。
命令行调试
使用curl命令,通过–header和–data-raw参数构造请求,配合–trace-ascii输出完整请求内容,便于对比签名,也可以使用postman,其“Pre-request Script”脚本可动态计算签名,部分社区提供了签名库。
本地脚本对比
编写一个Python脚本,分别模拟客户端和服务端签名逻辑,将中间结果输出到两个文件,用diff工具比较,如果差异只在一处,快速定位。
SDK自动签名
多数情况下,直接使用官方SDK是最省心的方式,SDK内部处理了Header排序、Body哈希、时间戳生成等细节,但需注意:某些SDK在自定义Header方面不灵活,如果业务需要添加额外签名头,可能需要手动扩展。
HTTP Header签名和Body签名常见问题
什么是HTTP Header签名?
HTTP Header签名是对请求头中的关键字段(如Date、Host、Content-Type等)进行加密签名,并将签名值放入请求头,服务端通过相同算法重新计算并与签名比对,以验证请求头是否被改动,同时确认调用方身份,它是API签名体系的基础组成部分。
HTTP Body签名如何实现?
通常做法是:先对HTTP请求体(Payload)进行SHA256哈希,得到摘要值,将该摘要值作为“虚拟Header”(如X-Content-Sha256)参与签名计算,客户端在Authorization头中包含签名后的结果,服务端接收到请求后,重新计算Body哈希并与客户端提供的哈希比对,再验证整个签名,确保Body在传输过程中未被修改。
签名验证失败时应该检查什么?
首先检查客户端与服务端的时间是否同步,时间差超过5分钟会导致签名直接失效,然后对比两端的待签名字符串,确认Header排序、Body哈希值、查询参数是否完全一致,接着确认签名算法是否为HMAC-SHA256,以及AccessKey和SecretKey是否正确,最后排查是否有代理或网关修改了请求头或Body,导致服务端接收到的内容与客户端发送的不一致。
