OAuth 1.0 请求返回 Invalid signature,通常不是 Token 权限不足,而是客户端和服务器计算出的 signature base string 不同。密钥不要打印到日志;只记录 HTTP 方法、规范化 URL、参数名、时间戳和签名算法即可定位。

先区分认证类型

Bearer integration token 不使用 OAuth 签名。如果 Authorization 头以 OAuth 开头,才检查 consumer key、token、nonce、timestamp 和 signature。先用同一凭据请求简单只读接口,排除资源 ACL。

date -u +%s
timedatectl status
curl -I https://shop.example.com/rest/V1/store/storeConfigs

打印脱敏后的签名基串

签名基串由大写 HTTP 方法、百分号编码后的基础 URL 和排序后的参数串组成。查询参数与 OAuth 参数都要参与排序,%20 不能替换成 +,重复编码也会失败。

METHOD=GET
BASE_URL='https://shop.example.com/rest/V1/products'
# 日志仅输出参数名和编码结果,不输出 consumer_secret/token_secret

Postman、SDK 与自研客户端任选两种发送同一请求。SDK 成功而自研失败,就逐字符比较 base string;两者都失败,检查服务器凭据、时间和代理。

代理后的协议与 Host

php bin/magento config:show web/secure/base_url
php bin/magento config:show web/unsecure/base_url
grep -R "X-Forwarded-Proto|fastcgi_param HTTPS" /etc/nginx 2>/dev/null

客户端签的是 HTTPS 域名,而 Magento 在代理后识别成 HTTP 或另一个 Host,也会计算出不同 URL。修复可信代理头配置,不要让应用无条件信任来自公网的伪造头。

时间戳与 nonce

时间戳必须接近服务器 UTC,nonce 每次请求唯一。重放完全相同的 Authorization 头可能被拒绝。修复后连续发送三次不同 nonce 的只读请求,再测试带查询参数和 POST body 的接口,确认编码规则一致。

生产环境操作前的检查

针对“Magento 2 REST API 提示 Invalid signature”进行处理时,先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT;需要 UPDATE、DELETE、补偿命令或目录删除时,必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、app/etc/env.php 摘要和当前流量节点,避免只修复其中一台。

php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status

命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务;若涉及数据库结构、库存、支付或订单,先在脱敏的生产数据副本验证,再安排维护窗口。

建立可比较的排查记录

每次实验只改变一个变量,并保存“操作前值、执行命令、开始时间、结束时间、结果、回滚方式”。至少准备一个正常对象和一个异常对象作对照,例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复,而新建对象仍会复现,说明根因尚未消除。

检查点需要记录通过标准
数据层 主键、Store/Website、更新时间、关联行数 关系完整且无孤儿记录
应用层 异常堆栈、模块、Cron/消费者状态 无新异常并可重复执行
缓存与索引 索引模式、版本、源站和公网响应 按预期周期自动更新
业务回归 正常路径、失败路径、重复请求 结果一致且没有重复副作用

修复后的观察窗口

上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期,并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项;确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息,采集时要脱敏,问题结束后及时关闭。