集成拿到了 consumer key、consumer secret、access token 与 token secret,但请求 Magento 2 REST API 返回 The signature is invalid. Verify and try again.。重新创建 Integration 有时会暂时“解决”,更多时候只是把原有参数覆盖。OAuth 1.0 的签名对每一个字符敏感,必须比较双方实际参与计算的内容。

固定一条最简单的请求

先用 GET 请求一个权限允许、没有复杂 body 的端点,保存 HTTP method、完整 URL、Authorization header 与响应。调试日志中密钥必须脱敏,nonce 和 timestamp 可以保留用于复现。

签名基础字符串由大写方法、规范化 base URL、规范化参数三部分组成。以下差异都会产生完全不同的 HMAC:

  • 客户端签的是 http,代理外部访问却是 https;
  • URL 带默认端口或尾斜杠,服务端规范化后不同;
  • query 参数排序、重复参数或空值处理不同;
  • 空格用加号编码,而 OAuth 需要 RFC 3986 百分号编码;
  • oauth_signature 本身放进待签参数。

打印 base string,不要打印 secret

在客户端库签名前增加临时调试,输出 normalized URL、参数排序结果和 signature base string。Magento 侧在隔离测试环境增加对应日志,比较第一个不同字符。生产环境不要记录完整 Authorization header,因为 token 可被重放利用。

GET&https%3A%2F%2Fwww.example.com%2Frest%2FV1%2Fstore%2FstoreConfigs&oauth_consumer_key%3D...

这只是结构示例,不可直接作为签名输入。实际字符串必须包含本次请求的全部 OAuth 参数和查询参数。

代理和 Base URL 经常是根因

Magento 部署在负载均衡后时,如果 secure/offloader header 配置错误,应用认为请求来自 HTTP,而客户端按 HTTPS 签名。检查 Web server、trusted proxy、Base URL 与 Host 转发。客户端签名 URL 必须与 Magento 用来验证的有效请求 URL 一致,不能用容器内部主机名签名再通过公网域名发送。

时间戳与 nonce 是另一类错误

服务器和客户端时间偏差过大、重复 nonce、秒和毫秒混用,也会让鉴权失败。先使用 NTP/chrony 校时,确认 timestamp 是 Unix 秒。若错误信息明确为 nonce 已使用,不要把它混同为 HMAC 计算错误。

密钥组合顺序

HMAC-SHA256/HMAC-SHA1 具体实现取决于客户端与 Magento 支持配置,但 signing key 的组成应是编码后的 consumer secret 与 token secret,中间用 & 连接。常见错误是交换 key/secret、使用 Integration 激活前的旧 token,或把显示时复制到的空格一并保存。

POST body 是否进入签名

JSON body 通常不按表单参数加入 OAuth 1.0 参数归一化;application/x-www-form-urlencoded 则需要按规范处理。客户端库如果不区分 Content-Type,会出现 GET 成功、POST 失败。先比较请求头和库版本,再决定是否调整参数收集。

最后再轮换凭据

只有确认 base string 一致仍无法验证,或密钥可能泄露时,才撤销并重新激活 Integration。轮换会中断现有调用方,应先盘点使用者。修复完成后用固定测试请求通过,再测试带 query、JSON POST 和反向代理路径;同时删除临时签名日志。这样才能证明问题不是被新 token 偶然掩盖。