如何在Spring Boot中实现draft-cavage-http-signatures-10签名规范
问题1:KeyId的定义与作用
- KeyId是密钥的唯一标识符,相当于你给当前使用的签名密钥约定的唯一名称
- 核心作用是让服务端收到请求后,无需遍历全量密钥,直接通过KeyId快速定位到对应验签公钥,也可以明确识别本次签名使用的密钥版本,特别适配多租户、密钥定期轮转的场景
- 你示例中的
keyId="Test"就是提前和服务端约定好的密钥ID,服务端会提前存储ID为Test对应的RSA公钥,收到请求后直接调取该公钥做验签即可
问题2:signature值的定义与生成方法
signature是按照规范规则将请求的核心信息拼接成字符串后,用你持有的私钥按照指定算法加密得到的Base64编码结果,服务端会用对应公钥解密后和自己拼接的请求信息做对比,结果一致就能证明请求未被篡改、发起方是持有对应私钥的合法主体。
具体生成步骤(以你示例中的rsa-sha256算法为例)
- 确定签名头列表
规范默认最少需要签名(request-target)、Host、Date三个字段,也可以和服务端约定增加Content-Type、Digest等其他请求头,包含的字段越多安全性越高。示例:如果你要发送POST请求到
/api/order接口,请求Host为api.xxx.com,请求时间Date为Tue, 07 May 2024 09:12:34 GMT,那么约定的签名头列表就是(request-target) host date - 拼接签名字符串
所有参与签名的字段统一按头名小写: 头值的格式拼接,每个字段占一行,最后一行不要留空行。
上述示例拼接后的签名字符串为:(request-target): post /api/order host: api.xxx.com date: Tue, 07 May 2024 09:12:34 GMT - 计算签名值
- 用你的RSA私钥对上面拼接好的字符串先做SHA256哈希,再做RSA私钥签名
- 将签名后得到的二进制结果做Base64编码,得到的字符串就是signature字段的值
- 拼接Authorization头
按示例格式将keyId、algorithm、headers(你签名用的头列表)、signature拼接成完整的Authorization头即可。
Spring Boot实现参考
你可以直接使用已经实现了该规范的第三方工具包org.tomitribe:tomitribe-http-signatures,不需要从零手写所有逻辑,核心调用逻辑示例:
// 构造签名基础参数 Signature signature = new Signature(); signature.setKeyId("Test"); signature.setAlgorithm("rsa-sha256"); // 传入私钥生成签名器 Signer signer = new RsaSha256Signer(yourRsaPrivateKey); // 传入拼接好的签名字符串,直接得到signature值 String signatureValue = signer.sign(signingString);
注意必须提前和服务端对齐签名的头列表、算法、编码规则,任何一点不一致都会导致验签失败。
内容的提问来源于stack exchange,提问作者Asanka Anthony
相关产品推荐
相关产品推荐

