api - Amazon product lookup signature mismatch
问题描述
This is the response I'm getting: The request signature we calculated does not match the signature you provided.
Here is the code I'm using to generate the signature:
static byte[] HmacSHA256(String data, byte[] key)
{
String algorithm = "HmacSHA256";
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName)
{
byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray());
byte[] kDate = HmacSHA256(dateStamp, kSecret);
byte[] kRegion = HmacSHA256(regionName, kDate);
byte[] kService = HmacSHA256(serviceName, kRegion);
byte[] kSigning = HmacSHA256("aws4_request", kService);
return kSigning;
}
When I use Amazon's test settings, I get the correct signature
key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'
However, when I put my live settings in, I get the not matching error.
Here is what I'm using to get my signature:
var reqSig = getSignatureKey("[my secret key]", dateStamp, "us-west-2","AWSECommerceService");
This is what I'm submitting (I'm just testing it in a browser, for now):
ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=[my
access key that corresponds with the secret
key]&Operation=ItemLookup&IdType=UPC&ItemId=635753490879&Timestamp=2019-01-24T19:14:55.2644840Z&Signature=32BA07ECE67F3177BF2EA02923E624D612A45FAA144ED0E43BDDC0DF6574EAC3
I'm not sure if it has to do with the region -- us-west-2 in my case -- because there is no place on the request for a region. I'm not sure how Amazon can test my signature against my parameters if I can't specify what region it is and I've used the region to calculate the signature.
What am I missing?
解决方案
好的。在花了几天的时间经历这个之后,这是我必须做的:
/*
DOCUMENTATION: https://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html#rest_detailedexample
*/
var itemID = "0679722769";
var accessKeyID = "AKIAIOSFODNN7EXAMPLE";
var timeStamp = DateTime.UtcNow.ToString("o");
var req = $"Service=AWSECommerceService&AWSAccessKeyId={accessKeyID}&Operation=ItemLookup&IdType=UPC&ItemId={itemID}&Version=2013-08-01&Timestamp={timeStamp}";
req = req.Replace(":", "%3A").Replace(",", "%2C"); //UrlDecode certain characters
var reqlist = req.Split('&').ToArray(); //we need to sort our key/value pairs
Array.Sort(reqlist);
req = String.Join("&", reqlist); //join everything back
var reqToSign = $@"GET
webservices.amazon.com
/onca/xml
{req}".Replace("\r", ""); //create the request for signing. We need to replace microsofts's crlf with just a lf; Make sure there are no leading spaces after the linefeeds.
var signage = getSignatureKey("1234567890",reqToSign);
req = $"http://webservices.amazon.com/onca/xml?{req}&Signature={signage}"; //create our request with the signature appended.
return req;
}
private static byte[] HmacSHA256(String data, byte[] key)
{
String algorithm = "HmacSHA256";
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
private static string getSignatureKey(string key, string stringToSign)
{
byte[] kSecret = Encoding.UTF8.GetBytes(key.ToCharArray());
byte[] kSigning = HmacSHA256(stringToSign, kSecret);
return WebUtility.UrlEncode(Convert.ToBase64String(kSigning));
}
与在这里和其他地方找到的大多数答案相反,这是唯一可行的方法。必须对整个请求进行哈希处理,而不仅仅是特定参数。我无法与其他亚马逊服务交谈,但商务服务必须这样做。
相当多的答案引用了这个:https ://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html或这个:Amazon API 在 C# .NET 中生成请求签名
正如我在问题中所说,这肯定是不正确的。如果您没有传递区域参数,亚马逊如何创建相同的签名,因为它没有所有信息。
无论如何,这现在有效。
推荐阅读
- r - 减少嵌套for循环R中不必要的重复读取文件
- mysql - 具有相乘列的已付款发票的 Laravel 范围
- r - 使用 ggplot 和 gganiminate 的动画条形图
- jquery - ../../../../ 中的错误找不到命名空间“嘶嘶声”
- google-apps-script - 使用 urlFetchApp 登录后如何获取源代码?
- flutter - Flutter Provider:如何通知模型它包含的模型发生了变化?
- python - 熊猫在一列中的每个值在另一列中的项目数
- php - 在 laravel 中为用户创建新密码
- android - 为按钮创建样式
- reactjs - Redux 操作可以在 React 中调度和返回一些东西吗