【问题标题】:Request signature does not match in Amazon API (string to sign)Amazon API 中的请求签名不匹配(要签名的字符串)
【发布时间】:2018-10-11 12:20:55
【问题描述】:

我尝试使用 Google Apps 脚本对 Amazon 进行 API 调用,以获取有关市场中 ID 为 XXX-XXXXXX-XXXXXX 的订单的信息:UK - A1F83G8C2ARO7P。

我总是得到回应:

<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.</Message>

我按照文档做了一切,我使用了这个例子:

Using GET with Authentication Information in the Query String (Python).

对于散列,我使用了库:jsSHA 和 SHA 变体 SHA-256。

我认为在公式中:

signature = HexEncode(HMAC(derived signing key, string to sign)) 我在第二部分中实现了一些错误:string to sign 但无法弄清楚到底是什么。

function amazonGetQuery () {

var date = new Date(); 
var amz_date  = date.toISOString(); //2018-05-01T20:40:50.940Z

var yearMonthDay= Utilities.formatDate(date, 'UTC', 'yyyyMMdd');
var hourMinuteSec = Utilities.formatDate(date, 'UTC', 'HHmmss');

var dateForStringToSign = yearMonthDay +'T'+hourMinuteSec+'Z'; //20180501T204050Z

var datestamp = yearMonthDay; // 20180501

var access_key = "XXXXXXXXXXXXXXX";

var method = 'GET';
var service = 'mws'
var host = 'mws.amazonservices.co.uk';
var region = 'eu-west-2';
var endpoint = 'https://mws.amazonservices.co.uk/Orders/2013-09-01';


var canonical_uri = '/Orders/2013-09-01';
var canonical_headers = 'host:' + host + '\n';
var signed_headers = 'host';


//# Match the algorithm to the hashing algorithm you use, either SHA-1 or
//# SHA-256 (recommended)
var algorithm = 'AWS4-HMAC-SHA256';
var credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';

Logger.log('credential_scope: '+credential_scope);

//# Step 4: Create the canonical query string. In this example, request
//# parameters are in the query string. Query string values must
//# be URL-encoded (space=%20). The parameters must be sorted by name

var canonical_querystring =  'AWSAccessKeyId='+encodeURIComponent('XXXXXXXXXXXXXX');
    canonical_querystring += '&Action='+encodeURIComponent('GetOrder');
    canonical_querystring += '&AmazonOrderId.Id.1='+encodeURIComponent('XXX-XXXXXX-XXXXXX');
    canonical_querystring += '&MWSAuthToken='+encodeURIComponent('xxx.xxx.xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx');
    canonical_querystring += '&MarketplaceId.Id.1='+encodeURIComponent('A1F83G8C2ARO7P');
    canonical_querystring += '&SellerId='+encodeURIComponent('XXXXXXXXXXX');
    canonical_querystring += '&SignatureMethod='+encodeURIComponent('HmacSHA256');
    canonical_querystring += '&SignatureVersion='+encodeURIComponent('2');
    canonical_querystring += '&Timestamp='+encodeURIComponent(amz_date);
    canonical_querystring += '&Version='+encodeURIComponent('2013-09-01');
    canonical_querystring += '&X-Amz-Algorithm='+encodeURIComponent('AWS4-HMAC-SHA256');
    canonical_querystring += '&X-Amz-Credential='+encodeURIComponent(access_key + '/' + credential_scope);
    canonical_querystring += '&X-Amz-Date='+encodeURIComponent(amz_date);
    canonical_querystring += '&X-Amz-Expires=2';
    canonical_querystring += '&X-Amz-SignedHeaders='+encodeURIComponent(signed_headers);


//singing key
var shaObj = new jsSHA("SHA-256", "TEXT");
shaObj.setHMACKey("41575334XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX456", "HEX"); // 
shaObj.update(datestamp);
var hmac = shaObj.getHMAC("HEX");

var shaObj2 = new jsSHA("SHA-256", "TEXT");
shaObj2.setHMACKey(hmac, "HEX");
shaObj2.update(region);
var hmac2 = shaObj2.getHMAC("HEX");


var shaObj3 = new jsSHA("SHA-256", "TEXT");
shaObj3.setHMACKey(hmac2, "HEX");
shaObj3.update(service);
var hmac3 = shaObj3.getHMAC("HEX");

var shaObj4 = new jsSHA("SHA-256", "TEXT");
shaObj4.setHMACKey(hmac3, "HEX");
shaObj4.update("aws4_request");
var signing_key = shaObj4.getHMAC("HEX");


//# Step 5: Create payload hash. For GET requests, the payload is an
//# empty string ("").
//Example hashed payload (empty string)
//e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
var shaObj1 = new jsSHA("SHA-256", "TEXT");
shaObj1.update('');
var payload_hash = shaObj1.getHash("HEX");

Logger.log('payload_hash: \n'+payload_hash);

//# Step 6: Combine elements to create canonical request
var canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' +payload_hash;

Logger.log('cannonical_request: \n'+canonical_request)

//Hashed canonical request
var shaObj7 = new jsSHA("SHA-256", "TEXT");
shaObj7.update(canonical_request);
var hashed_canonical_request = shaObj7.getHash("HEX");
Logger.log('hashed_canonical_request: \n'+hashed_canonical_request);


//stringTosign
var string_to_sign = algorithm + '\n' +  dateForStringToSign + '\n' +  credential_scope + '\n' + hashed_canonical_request; 
Logger.log('string_to_sign: \n'+string_to_sign);

//SIGNATURE
var shaObj5 = new jsSHA("SHA-256", "TEXT");
shaObj5.setHMACKey(signing_key, "HEX");
shaObj5.update(string_to_sign);
var signature = shaObj5.getHMAC("HEX");
Logger.log('signature: \n'+signature);

canonical_querystring += '&Signature=' + signature;

var request_url = endpoint + '?' + canonical_querystring;

Logger.log('request_url: '+request_url+'\n')


 var options = {

      'method' : 'get',
      'muteHttpExceptions':true,
      'host': host,

 }

UrlFetchApp.fetch(request_url, options);



}

结果:

credential_scope:

20180501/eu-west-2/mws/aws4_request

cannonical_request:

GET
/Orders/2013-09-01
AWSAccessKeyId=XXXXXXXXXXXX&Action=GetOrder&AmazonOrderId.Id.1=XXX-XXXXXX-XXXXXX&MWSAuthToken=xxxx.xxxx.xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx&MarketplaceId.Id.1=A1F83G8C2ARO7P&SellerId=XXXXXXXXX&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2018-05-01T12%3A02%3A18.889Z&Version=2013-09-01&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXX%2F20180501%2Feu-west-2%2Fmws%2Faws4_request&X-Amz-Expires=2&X-Amz-Date=2018-05-01T12%3A02%3A18.889Z&X-Amz-SignedHeaders=host
host:mws.amazonservices.co.uk

host
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

string_to_sign:

AWS4-HMAC-SHA256
20180501T205153Z
20180501/eu-west-2/mws/aws4_request
XXX436XXXXXXXX3d5beXXXdec39XXXXXXXXXXXXXXXX1d57fb33XXXXXc

request_url:

https://mws.amazonservices.co.uk/Orders/2013-09-01?AWSAccessKeyId=XXXXXXXXXXXXXX&Action=GetOrder&AmazonOrderId.Id.1=xxx-xxxxxx-xxxxxxx&MWSAuthToken=xxxx.xxx.xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx&MarketplaceId.Id.1=A1F83G8C2ARO7P&SellerId=XXXXXXXXXXXXXXXX&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2018-05-01T12%3A02%3A18.889Z&Version=2013-09-01&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXXXXX%2F20180501%2Feu-west-2%2Fmws%2Faws4_request&X-Amz-Expires=2&X-Amz-Date=2018-05-01T12%3A02%3A18.889Z&X-Amz-SignedHeaders=host&Signature=a29XXXXXXXXXXXXXXXXX863b0ade00881XXXXXXXXXXXX1ae1216XXXX

【问题讨论】:

  • 在您的字符串签名中,第二行应该是YYYYMMDDTHHMMSSZ,即。 20180501T120218Z。我也不明白为什么在您的代码中,signing_keyhashed_canonical_requestsignature 是静态字符串。所有这些都是在签名过程中构建的,每次运行时。
  • 迈克尔,感谢您的快速响应。我会根据您的建议尝试更改日期。在我的原始代码中,signing_key、hashed_canonical_request 和 signature 不是静态值,我只是将其添加为静态值,因为我想主要关注 string_to_sign。
  • 它们随每个请求而变化(签名密钥除外,它仅在日期、区域、服务或秘密不同时才会改变),因此您无法可靠地排除字符串故障以使用静态值签名这些其他的东西——特别是签名,它部分来自于字符串签名。
  • 我替换了 string_to_sign 中的时间格式,但响应是一样的。另外,我添加了脚本的完整代码,也许你可以在我的代码中发现另一个错误。 @signing 密钥应该是正确的,因为我使用 API 文章中的值对其进行了测试:docs.aws.amazon.com/general/latest/gr/… 并得到了预期的结果。
  • 这两行颠倒过来:canonical_querystring += '&amp;X-Amz-Expires=2'; canonical_querystring += '&amp;X-Amz-Date='+encodeURIComponent(amz_date); 规范查询字符串需要按字节顺序排序的键。

标签: javascript amazon-web-services google-apps-script amazon-mws


【解决方案1】:

我大约在 2 年前发布了这个问题,最近这篇帖子有一些活动,所以我想分享一个技巧,它帮助我成功地发出 API 请求。亚马逊有专门的在线 API 请求测试工具,叫做:Amazon Scratchpad。如果您通过此页面获得响应而没有任何错误,那么您可以比较代码中的输入数据并轻松找到错误。

每个市场的 Scratchpad URL 都不同,即:对于 DE 是 https://mws.amazonservices.de/scratchpad/index.html,对于英国是 https://mws.amazonservices.co.uk/scratchpad/index.html 等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 2017-10-10
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多