You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Magento 2 REST API OAuth签名无效:Postman正常Node-Red(Node.js)报错求助

Magento 2 OAuth签名不匹配问题

我尝试通过OAuth认证调用Magento 2 REST API,该调用在Postman中可正常执行,但在Node-Red(基于Node.js)中调用时返回错误:"签名无效,请验证后重试"。

我将签名生成脚本的参数调整为与Postman一致后,生成的OAuth签名仍和Postman的不匹配,相关信息如下:

我的签名生成脚本

//Variables required from the function calling this flow
var p_http_method = "GET";
var p_url = "https://watchguard24.co.za/rest/V1/modules/";

//Static variables for Magento authorization
const p_oauth_version = "1.0";
const p_signature_method = "HMAC-SHA256";
const p_nonce = "17TTbZZM0fi" //encodeURIComponent(uuid.v4()); //"35WpXRWuoQp" //uuid.v4();
const p_consumer_key = "wypklfmtf6m53b0rfclxikr2xibopftu";
const p_access_token = "umnmupjtpidzuzz47vuo5s2ianxmq7cf";
const p_consumer_secret = encodeURIComponent("fw17d1k3i70zldcy7xvuvtjjykrzw286");
const p_token_secret = encodeURIComponent("lroq3mg3vteogfisez7hu2zwbu7fmq2x");
const p_timestamp = 1668081726 //Math.floor(Date.now() / 1000);

//Combining OAuth parameters
const parameters = {
    oauth_consumer_key: p_consumer_key,
    oauth_nonce: p_nonce,
    oauth_signature_method: p_signature_method,
    oauth_timestamp: p_timestamp,
    oauth_version: p_oauth_version,
    oauth_token: p_access_token
}

//Ordering and encoding the variables
let ordered = {};
Object.keys(parameters).sort().forEach(function (key) {
    ordered[key] = parameters[key];
});

let encodedParameters = '';

for (var k in ordered) {
    const encodedValue = encodeURIComponent(ordered[k]);
    const encodedKey = encodeURIComponent(k);
    if (encodedParameters === '') {
        encodedParameters += encodeURIComponent(`${encodedKey}=${encodedValue}`)
    }
    else {
        encodedParameters += encodeURIComponent(`&${encodedKey}=${encodedValue}`);
    }
}

//Base signature string
const encodedUrl = encodeURIComponent(p_url);

encodedParameters = encodeURIComponent(encodedParameters);

const signature_base_string = encodeURIComponent(`${p_http_method}&${encodedUrl}&${encodedParameters}`)

//Create the oauth signature
const signing_key = `${p_consumer_secret}&${p_token_secret}`

const oauth_signature = crypto.createHmac("sha256", signing_key).update(signature_base_string).digest('base64');

//Encode oauth signature
const encoded_oauth_signature = encodeURIComponent(oauth_signature);

msg.headers = {
    "Authorization": 
        'OAuth oauth_consumer_key=' + p_consumer_key 
        + ',oauth_token=' + p_access_token 
        + ',oauth_signature_method=' + p_signature_method
        + ',oauth_timestamp=' + p_timestamp
        + ',oauth_nonce=' + p_nonce
        + ',oauth_signature=' + encoded_oauth_signature
        + ',oauth_version=' + p_oauth_version
}

return msg;

Postman生成的Authorization头

OAuth 
oauth_consumer_key="wypklfmtf6m53b0rfclxikr2xibopftu",
oauth_token="d07jwep9s79srvy3dmjltlfafnpl9d1d",
oauth_signature_method="HMAC-SHA256",
oauth_timestamp="1668081726",
oauth_nonce="17TTbZZM0fi",
oauth_version="1.0",
oauth_signature="yktg8XIKp%2Fsjk2Wzr4Qk7Mxs6B7kY%2Fjx3040UvwHuY8%3D"

Node-Red生成的Authorization头

OAuth 
oauth_consumer_key=wypklfmtf6m53b0rfclxikr2xibopftu,
oauth_token=d07jwep9s79srvy3dmjltlfafnpl9d1d,
oauth_signature_method=HMAC-SHA256,
oauth_timestamp=1668081726,
oauth_nonce=17TTbZZM0fi,
oauth_version=1.0,
oauth_signature=8GPa253AV9I%2FIGB9N2s2Urbg7Km%2FUcjhzM%2BeRjuEag4%3D

我已参考Magento 2官方OAuth认证文档及相关Node.js OAuth签名生成教程,但问题仍未解决,需要修正脚本使生成的OAuth签名与Postman一致,以成功调用API。


修正后的脚本及问题说明

你的脚本存在3个关键错误,导致签名不匹配:

  1. 签名基字符串重复编码:按照OAuth 1.0a规范,只需要分别编码HTTP方法、URL、参数串后用&拼接,不需要再对整个拼接结果编码。
  2. 参数串构建逻辑错误:原脚本对每个key=value片段单独编码,会导致=和&被二次编码,正确做法是先编码key和value,拼接成key=value后用&连接所有项,最后对整个参数串做一次编码。
  3. Authorization头缺少引号:Postman生成的头中每个参数值都用双引号包裹,原脚本未添加,这会导致认证校验失败。

修正后的脚本:

//Variables required from the function calling this flow
var p_http_method = "GET";
var p_url = "https://watchguard24.co.za/rest/V1/modules/";

//Static variables for Magento authorization
const p_oauth_version = "1.0";
const p_signature_method = "HMAC-SHA256";
const p_nonce = "17TTbZZM0fi";
const p_consumer_key = "wypklfmtf6m53b0rfclxikr2xibopftu";
const p_access_token = "d07jwep9s79srvy3dmjltlfafnpl9d1d"; // 与Postman使用的token保持一致
const p_consumer_secret = "fw17d1k3i70zldcy7xvuvtjjykrzw286"; // 不要提前编码,签名时再处理
const p_token_secret = "lroq3mg3vteogfisez7hu2zwbu7fmq2x";
const p_timestamp = 1668081726;

//Combining OAuth parameters
const parameters = {
    oauth_consumer_key: p_consumer_key,
    oauth_nonce: p_nonce,
    oauth_signature_method: p_signature_method,
    oauth_timestamp: p_timestamp,
    oauth_version: p_oauth_version,
    oauth_token: p_access_token
}

// 1. 按字典序排序参数并生成编码后的键值对
const sortedKeys = Object.keys(parameters).sort();
let paramPairs = [];
for (const key of sortedKeys) {
    const encodedKey = encodeURIComponent(key);
    const encodedValue = encodeURIComponent(parameters[key]);
    paramPairs.push(`${encodedKey}=${encodedValue}`);
}
// 2. 拼接参数串并编码
const encodedParameters = encodeURIComponent(paramPairs.join('&'));
// 3. 编码HTTP方法(需大写)和URL
const encodedMethod = encodeURIComponent(p_http_method.toUpperCase());
const encodedUrl = encodeURIComponent(p_url);
// 4. 构建签名基字符串
const signature_base_string = `${encodedMethod}&${encodedUrl}&${encodedParameters}`;

// 生成签名密钥:编码consumer secret和token secret后用&连接
const signing_key = `${encodeURIComponent(p_consumer_secret)}&${encodeURIComponent(p_token_secret)}`;

// 生成HMAC-SHA256签名并转base64
const oauth_signature = crypto.createHmac("sha256", signing_key)
    .update(signature_base_string)
    .digest('base64');

// 编码签名
const encoded_oauth_signature = encodeURIComponent(oauth_signature);

// 构建带双引号的Authorization头
msg.headers = {
    "Authorization": 
        `OAuth oauth_consumer_key="${p_consumer_key}"`
        + `,oauth_token="${p_access_token}"`
        + `,oauth_signature_method="${p_signature_method}"`
        + `,oauth_timestamp="${p_timestamp}"`
        + `,oauth_nonce="${p_nonce}"`
        + `,oauth_signature="${encoded_oauth_signature}"`
        + `,oauth_version="${p_oauth_version}"`
};

return msg;

额外注意点

  • 确保p_access_token与Postman中使用的完全一致(原脚本中的token和Postman里的不匹配)
  • 签名基字符串中的HTTP方法必须大写
  • 不要提前编码consumer secret和token secret,在生成signing key时再进行编码

内容的提问来源于stack exchange,提问作者Renier Duvenhage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 04:30:57