hash_hmac是防篡改+身份确认的标准签名方案,需密钥、不可逆、抗碰撞;md5/sha1无密钥易被重放;Laravel中间件须用getContent(false)取原始请求体,timestamp校验±5分钟,nonce防重放,字段须放header且严格一致。

签名用 hash_hmac 而不是 md5 或 sha1
签名的核心是防篡改+身份确认,必须带密钥、不可逆、抗碰撞。md5 和 sha1 没有密钥,纯哈希容易被重放或伪造;hash_hmac 是标准选择,Laravel 自带支持,密钥不暴露、输出稳定。
- 服务端和客户端必须用完全相同的密钥(建议存在配置里,别硬编码)
- 签名原文必须固定顺序拼接:通常为
method+uri+timestamp+nonce+body_md5(如有 JSON body) - 注意:
timestamp应校验有效期(如 ±5 分钟),否则签名形同虚设 - 不要对 query string 做 URL decode 后再签名——客户端编码后传什么,服务端就拿什么拼
Laravel 中间件里怎么取原始请求体做签名比对
默认 Laravel 的 $request->getContent() 在中间件里可能为空,因为后续逻辑(比如 FormRequest)会提前解析并清空流。签名验证必须在最前,且要确保能读到原始字节。
- 在中间件的
handle方法开头立刻调用$request->instance()->getContent(false)(false表示不刷新流) - 如果用了
json或form-data,别依赖$request->all()拼签名——它已解码/过滤,和客户端发的原始结构不一致 - Body 为空时,
body_md5应统一约定为md5('')(即'd41d8cd98f00b204e9800998ecf8427e'),避免空值处理差异 - 验证失败直接
return response('', 401),别抛异常——异常可能被全局 handler 捕获并返回 500,掩盖真实问题
客户端签名时 timestamp 和 nonce 怎么传才不踩坑
这两个字段看着简单,但错一个字符整个签名就失效,而且调试极难定位。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
-
timestamp必须是秒级整数(不是毫秒),且客户端和服务端时钟误差需控制在允许窗口内(推荐用 NTP 校准,或让客户端从服务端接口先拉一次时间) -
nonce是一次性的随机字符串(推荐bin2hex(random_bytes(16))),不能重复,服务端需缓存近期用过的nonce(比如 Redis 5 分钟 TTL)防止重放 - 这两个字段必须放在请求头(如
X-Signature-Timestamp/X-Signature-Nonce),别塞进 query 或 body——否则签名原文和实际传输内容不一致 - 别在 header 里加空格或换行,
trim()一下再参与签名计算
签名中间件注册顺序影响验证结果
签名验证必须在所有可能修改请求数据的中间件之前执行,否则签名原文和实际收到的内容对不上。
- 确保它在
TrimStrings::class、ConvertEmptyStringsToNull::class、ValidateSignature::class(如果用了 Laravel 自带签名)之前 - 不要放在
apimiddleware group 里靠后的位置;推荐单独定义一个signedgroup,在app/Http/Kernel.php的$middlewareGroups里前置声明 - 如果用了 Sanctum 或 Passport,签名中间件必须在认证中间件之前——签名是第一道门,认证是第二道
- 本地开发用 Postman 测试时,记得关掉「Automatically add Authorization header」这类自动行为,它会污染 header
签名最难的从来不是算法,而是两端对“原始数据”的定义是否完全一致:哪个字段参与、怎么编码、空值怎么处理、时间怎么对齐。差一个空格,验签就挂,而错误信息往往只回一个 401,没日志根本看不出哪一步偏了。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










