手动构造DynamoDB请求遇InvalidSignatureException问题求助
问题描述
我希望在Salesforce B2C Commerce Cartridge中不使用AWS SDK,直接向AWS DynamoDB发送HTTP请求。已遵循AWS DynamoDB低级别API及Signature Version 4文档手动构造请求,但遇到「InvalidSignatureException」错误,提示签名不匹配。以下是我的实现代码及输出:
规范请求代码
const payloadObject = { TableName: "tableName", ReturnConsumedCapacity: "TOTAL" } const payload = JSON.stringify(payloadObject); const date = new Date().toISOString().replace(/[:\-]|\.\d{3}/g, ''); const shortDate = date.substring(0, 8); const payloadHash = crypto.createHash('sha256').update(payload).digest('hex'); const canonicalRequest = [ 'POST', '/', '', 'action=scan', 'content-type:application/x-amz-json-1.0', 'host:dynamodb.eu-west-2.amazonaws.com', 'x-amz-content-sha256:' + payloadHash, 'x-amz-date:' + date, 'x-amz-target:DynamoDB_20120810.Scan', '', 'content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target', payloadHash ].join('\n'); const canonicalRequestHash = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
规范请求输出
POST / action=scan content-type:application/x-amz-json-1.0 host:dynamodb.eu-west-2.amazonaws.com x-amz-content-sha256:4aabc25ba680a6fe0d0cadc9754a0b249b7809904c2f495b1e28ffcea826c347 x-amz-date:20231230T095237Z x-amz-target:DynamoDB_20120810.Scan content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target 4aabc25ba680a6fe0d0cadc9754a0b249b7809904c2f495b1e28ffcea826c347
待签名字符串代码
const stringToSign = [ 'AWS4-HMAC-SHA256', date, shortDate + '/' + region + '/dynamodb/aws4_request', canonicalRequestHash ].join('\n');
待签名字符串输出
AWS4-HMAC-SHA256 20231230T095543Z 20231230/eu-west-2/dynamodb/aws4_request 2ca2fff7661d28aca561e03f48d80d53beed6d27d4422838e60ff3b006ef0f8c
签名计算代码
const dateKey = crypto.createHmac('sha256', 'AWS4' + secretKey).update(shortDate).digest(); const dateRegionKey = crypto.createHmac('sha256', dateKey).update(region).digest(); const dateRegionServiceKey = crypto.createHmac('sha256', dateRegionKey).update('dynamodb').digest(); const signInKey = crypto.createHmac('sha256', dateRegionServiceKey).update('aws4_request').digest(); const signature = crypto.createHmac('sha256', signInKey).update(stringToSign).digest('hex');
授权头构造代码
const AuthorizationHeader = `AWS4-HMAC-SHA256 Credential=${accessKey}/${shortDate}/${region}/dynamodb/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=${signature}`;
授权头输出
AWS4-HMAC-SHA256 Credential=*********/20231230/eu-west-2/dynamodb/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target, Signature=a9043338dbb2fd574e34a0b4ffac4a291e5c7c257c50775fa76746ca8438e90b
请求发送代码
axios.post('https://dynamodb.eu-west-2.amazonaws.com?Action=Scan', payload, { headers: { 'Content-Type': 'application/x-amz-json-1.0', 'Host': 'dynamodb.eu-west-2.amazonaws.com', 'X-Amz-Content-SHA256': payloadHash, 'X-Amz-Date': date, 'X-Amz-Target': 'DynamoDB_20120810.Scan', 'Authorization': AuthorizationHeader } }
错误响应
{ __type: 'com.amazon.coral.service#InvalidSignatureException', message: 'The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.' }
请问我哪里操作出错了?
问题分析与修正方案
以下是导致签名不匹配的核心问题及解决方法:
1. 日期不一致(最关键错误)
从输出可以看到:
- 规范请求中的
x-amz-date是20231230T095237Z - 待签名字符串中的日期是
20231230T095543Z
两者时间戳完全不同,这会导致AWS计算的签名和你生成的签名完全无法匹配。必须保证签名计算全程使用同一个时间戳,确保date变量只生成一次,且所有用到它的地方(规范请求、待签名字符串、请求头)都使用同一个值。
2. 错误添加了查询参数Action=Scan
DynamoDB的JSON API(通过X-Amz-Target指定操作类型)不需要在URL中添加?Action=Scan查询参数,你需要:
- 将请求URL改为
https://dynamodb.eu-west-2.amazonaws.com(去掉查询参数) - 修正规范请求,删除第四行的
action=scan,确保规范请求的第三行(查询字符串)为空,结构符合AWS要求:POST / content-type:application/x-amz-json-1.0 host:dynamodb.eu-west-2.amazonaws.com x-amz-content-sha256:4aabc25ba680a6fe0d0cadc9754a0b249b7809904c2f495b1e28ffcea826c347 x-amz-date:20231230T095237Z x-amz-target:DynamoDB_20120810.Scan content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target 4aabc25ba680a6fe0d0cadc9754a0b249b7809904c2f495b1e28ffcea826c347
3. 规范请求结构错误
AWS规范请求的正确结构是:
- HTTP方法
- URI路径
- 查询字符串(无则为空)
- 规范头部(每个头部键值对,小写、排序)
- 空行
- 签名头部列表(分号分隔,小写、排序)
- Payload哈希
原规范请求在第三行(查询字符串)后错误插入了action=scan,这不属于规范请求的任何部分,必须删除。
4. 额外检查点
- 确认
secretKey和accessKey完全正确,没有多余空格或字符 - 确认
region变量的值是eu-west-2,和请求的DynamoDB endpoint区域一致 - 确保Payload的JSON字符串没有意外的空格或格式差异(比如
JSON.stringify的输出是否和你计算哈希时完全一致)
内容的提问来源于stack exchange,提问作者voyager861
相关产品推荐
相关产品推荐

