NetSuite脚本对接Amazon SP API时STS签名不匹配问题求助
解决NetSuite对接Amazon SP API时STS签名不匹配问题
针对你遇到的STS AssumeRole请求签名不匹配错误,以下是代码中的关键问题及修正方案:
1. 规范查询字符串错误
AWS签名要求规范查询字符串不带开头的问号?,且所有查询参数需按ASCII升序排序。同时注意代码中RoleArn的笔误(mayactualARNe应为myactualARN)。
修正后的查询字符串:
const canonicalQuerystring = "Action=AssumeRole&DurationSeconds=3600&RoleArn=myactualARN&RoleSessionName=Test&Version=2011-06-15";
2. SignedHeaders未包含所有签名头部
你的canonicalHeaders包含了host和x-amz-date,但signedHeaders只声明了host,这会导致签名覆盖范围不匹配。需将所有参与签名的头部用分号分隔(小写、按顺序排列):
const signedHeaders = 'host;x-amz-date';
3. 空Payload哈希计算错误
GET请求的Payload为空,需明确对空字符串计算SHA256哈希,否则可能生成错误的哈希值:
const payloadHash = crypto.createHash({ algorithm: crypto.HashAlg.SHA256 }); payloadHash.update({ input: '' }); // 新增:对空字符串进行哈希计算 const payloadHashStr = payloadHash.digest().toLowerCase();
4. 签名结果格式错误
使用CryptoJS生成HMAC后,需将结果转换为十六进制小写字符串,否则签名格式不符合AWS要求:
const signature = CryptoJS.HmacSHA256(stringToSign, signingKey).toString(CryptoJS.enc.Hex);
5. 验证签名密钥生成逻辑
确保getSignatureKey函数严格按照AWS v4签名规范生成密钥:
- 先使用HMAC-SHA256对
"AWS4" + 秘钥以日期字符串为key计算哈希 - 再依次用区域、服务名、
"aws4_request"作为key迭代计算哈希
修正后的完整核心代码片段
const amzDate = getAmzDate(); const datestamp = amzDate.split("T")[0]; const host = "sts.amazonaws.com"; const canonicalUri = '/'; // 修正:去掉问号,参数按ASCII升序排列,修正RoleArn笔误 const canonicalQuerystring = "Action=AssumeRole&DurationSeconds=3600&RoleArn=myactualARN&RoleSessionName=Test&Version=2011-06-15"; const canonicalHeaders = `host:${host}\nx-amz-date:${amzDate}\n`; // 修正:包含所有签名头部 const signedHeaders = 'host;x-amz-date'; // 修正:正确计算空Payload的哈希 const payloadHash = crypto.createHash({ algorithm: crypto.HashAlg.SHA256 }); payloadHash.update({ input: '' }); const payloadHashStr = payloadHash.digest().toLowerCase(); const canonicalRequest = `GET\n${canonicalUri}\n${canonicalQuerystring}\n${canonicalHeaders}\n${signedHeaders}\n${payloadHashStr}`; log.debug("canonicalRequest", canonicalRequest); const credentialScope = `${datestamp}/${REGION}/${SERVICE_NAME_STS}/aws4_request`; const canonicalHash = crypto.createHash({ algorithm: crypto.HashAlg.SHA256 }); canonicalHash.update({ input: canonicalRequest }); const stringToSign = `${ALGORITHM}\n${amzDate}\n${credentialScope}\n${canonicalHash.digest().toLowerCase()}`; log.debug("stringToSign", stringToSign); const signingKey = getSignatureKey(amamzonConnectionKeysArray.secretkey, datestamp, REGION, SERVICE_NAME_STS); // 修正:转换为十六进制字符串 const signature = CryptoJS.HmacSHA256(stringToSign, signingKey).toString(CryptoJS.enc.Hex); const authorizationHeader = `${ALGORITHM} Credential=${amamzonConnectionKeysArray.accesskey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`; log.debug("authorizationHeader", authorizationHeader); const stsResponse = https.get({ url: amamzonConnectionKeysArray.urlsts, headers: { 'host': host, 'x-amz-date': amzDate, 'Authorization': authorizationHeader }, });
额外验证点
- 确认
REGION为us-east-1(STS全球端点默认区域,若使用区域端点需对应修改host和区域值) - 确认
SERVICE_NAME_STS为小写的"sts" - 检查
amamzonConnectionKeysArray.urlsts的域名与host完全一致(如https://sts.amazonaws.com)
内容的提问来源于stack exchange,提问作者Naveed Faraz
相关产品推荐
相关产品推荐

