[英]Amazon API generating a request signature in C# .NET
I'm trying to figure out how to pass a parameter in my .NET application. 我试图弄清楚如何在.NET应用程序中传递参数。 The URL request looks like: URL请求如下所示:
http://webservices.amazon.com/onca/xml?
Service=AWSECommerceService
&Operation=ItemLookup
&ResponseGroup=Large
&SearchIndex=All
&IdType=UPC
&ItemId=635753490879
&AWSAccessKeyId=[Your_AWSAccessKeyID]
&AssociateTag=[Your_AssociateTag]
&Timestamp=[YYYY-MM-DDThh:mm:ssZ]
&Signature=[Request_Signature]
The part that I'm confused about are these: 我感到困惑的部分是:
&Timestamp=[YYYY-MM-DDThh:mm:ssZ]
&Signature=[Request_Signature]
I'm not sure whether I can Just simply do it something like this for timestamp part: 我不确定是否可以在时间戳部分简单地执行以下操作:
var TimeStamp = DateTime.Now; // without any special datetime formating?
So my question is how do I actually generate this signature URL in the request URL ? 所以我的问题是我该如何在请求URL中实际生成此签名URL?
I have all of these parameters above but I'm not sure how to generate this last one ? 我上面有所有这些参数,但是我不确定如何生成最后一个?
Can someone help me out ? 有人可以帮我吗 ?
AWS utilizes HMAC request-signing. AWS利用HMAC请求签名。 Generally speaking, the way this works is that you create a "message", which is composed of things like your access key(s), request headers, request body and a timestamp. 一般而言,此方法的工作方式是创建一个“消息”,该消息由诸如访问密钥,请求标头,请求正文和时间戳之类的内容组成。 You then HMAC this "message" and that becomes your "signature" for the request. 然后,您向HMAC发送此“消息”,并成为请求的“签名”。 This prevents replay-attacks as each request must have a unique signature. 这可以防止重播攻击,因为每个请求必须具有唯一的签名。
It looks like the timestamp simply needs to be in ISO format ( YYYY-MM-DDThh:mm:ssZ
), so, no you can't just use DateTime.Now
. 看起来时间戳仅需要采用ISO格式( YYYY-MM-DDThh:mm:ssZ
),所以,不,您不能仅使用DateTime.Now
。 The default format utilized by ToString
will not be ISO. ToString
使用的默认格式将不是ISO。 Instead, you'd need to use something like: 相反,您需要使用以下方法:
DateTime.Now.ToString("yyyy-MM-ddThh:mm:sszzz");
Or it would actually probably be better to use UTC time and simply append a Z
: 或者,实际上最好使用UTC时间并简单地附加一个Z
:
DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ");
As for creating the signature, see the AWS documentation , where they provide some sample code: 至于创建签名,请参阅AWS文档 ,其中提供了一些示例代码:
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;
}
/*
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));
}
Contrary to most of the answers found here and elsewhere, this is the only way that works. 与这里和其他地方的大多数答案相反,这是唯一有效的方法。 The entire request has to be hashed, not just particular parameters. 必须对整个请求进行哈希处理,而不仅仅是特定的参数。 I can't speak to other Amazon services, but the Commerce Service has to be done like this. 我无法与其他Amazon服务交谈,但是必须像这样完成Commerce Service。
Quite a few answers here and elsewhere referenced this: https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html This is most certainly not correct. 这里和其他地方都引用了很多答案: https : //docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html这肯定是不正确的。 If you're not passing a region parameter, how can Amazon create the same signature since it doesn't have all the information. 如果您没有传递region参数,那么Amazon如何创建相同的签名,因为它没有所有信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.