Amazon API在C#.NET中生成请求签名
我正在尝试找出如何在.NET应用程序中传递参数。URL请求如下所示:Amazon API在C#.NET中生成请求签名,c#,asp.net,asp.net-mvc,amazon-web-services,c#-4.0,C#,Asp.net,Asp.net Mvc,Amazon Web Services,C# 4.0,我正在尝试找出如何在.NET应用程序中传递参数。URL请求如下所示: http://webservices.amazon.com/onca/xml? Service=AWSECommerceService &Operation=ItemLookup &ResponseGroup=Large &SearchIndex=All &IdType=UPC &ItemId=635753490879 &AWSAccessKeyId=
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]
我感到困惑的是:
&Timestamp=[YYYY-MM-DDThh:mm:ssZ]
&Signature=[Request_Signature]
我不确定是否可以简单地对时间戳部分执行类似的操作:
var TimeStamp = DateTime.Now; // without any special datetime formating?
所以我的问题是如何在请求URL中生成这个签名URL
我有上面所有的参数,但我不知道如何生成最后一个
有人能帮我吗?AWS使用HMAC请求签名。一般来说,其工作方式是创建一条“消息”,它由访问密钥、请求头、请求体和时间戳等组成。然后HMAC将此“消息”发送给您,并将其作为您请求的“签名”。这可以防止重播攻击,因为每个请求必须具有唯一的签名 看起来时间戳只需采用ISO格式(
YYYY-MM-DDThh:MM:ssZ
),因此,不,您不能只使用DateTime.Now
。ToString
使用的默认格式将不是ISO。相反,您需要使用以下内容:
DateTime.Now.ToString("yyyy-MM-ddThh:mm:sszzz");
或者,实际上最好使用UTC时间并简单地附加一个Z
:
DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ");
关于创建签名,请参见,其中他们提供了一些示例代码:
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;
}
AWS使用HMAC请求签名。一般来说,其工作方式是创建一条“消息”,它由访问密钥、请求头、请求体和时间戳等组成。然后HMAC将此“消息”发送给您,并将其作为您请求的“签名”。这可以防止重播攻击,因为每个请求必须具有唯一的签名 看起来时间戳只需采用ISO格式(
YYYY-MM-DDThh:MM:ssZ
),因此,不,您不能只使用DateTime.Now
。ToString
使用的默认格式将不是ISO。相反,您需要使用以下内容:
DateTime.Now.ToString("yyyy-MM-ddThh:mm:sszzz");
或者,实际上最好使用UTC时间并简单地附加一个Z
:
DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ");
关于创建签名,请参见,其中他们提供了一些示例代码:
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;
}
与这里和其他地方找到的大多数答案相反,这是唯一可行的方法。必须对整个请求进行散列,而不仅仅是特定的参数。我无法与其他亚马逊服务交谈,但商业服务必须这样做
这里和其他地方的许多答案都提到了这一点:
这肯定是不对的。如果您没有传递区域参数,Amazon如何创建相同的签名,因为它没有所有的信息
与这里和其他地方找到的大多数答案相反,这是唯一可行的方法。必须对整个请求进行散列,而不仅仅是特定的参数。我无法与其他亚马逊服务交谈,但商业服务必须这样做
这里和其他地方的许多答案都提到了这一点:
这肯定是不对的。如果您没有传递区域参数,Amazon如何创建相同的签名,因为它没有所有的信息 有人吗??有什么建议吗?有人吗??有什么建议吗?克里斯哇,非常感谢!!!我找到了这段代码,但我仍然对参数的“RegionName”和“ServiceName”部分感到困惑,我需要在这部分放些什么??这是AWS特有的东西,但我相信它们指的是你们的地区,因为AWS之类的云服务通常是地区特有的(
east-us-1
)。不管你在演什么,你都会去那里。该服务很可能就是您请求的特定AWS服务(例如,iam
),非常感谢!!传递到getSignatureMethod的日期戳如何,它是否需要以与时间戳相同的格式(yyyy-MM-ddThh:MM:ssZ)传递?是的。ISO日期对于任何类型的数据交换都是非常必要的。它之所以被称为ISO,是因为它是国际标准组织的标准格式,几乎是唯一可以普遍理解的日期格式。看起来AWS希望签名为十六进制摘要。在C#中,您可以通过String.Concat(bytes.Select(b=>b.ToString(“X2”)).ToArray()来获得它。不确定这是否重要,但AWS示例签名都是小写的,因此您可能还需要调用ToLower
。Chris wow非常感谢!!!我找到了这段代码,但我仍然对参数的“RegionName”和“ServiceName”部分感到困惑,我需要在这部分放些什么??这是AWS特有的东西,但我相信它们指的是你们的地区,因为AWS之类的云服务通常是地区特有的(east-us-1
)。不管你在演什么,你都会去那里。该服务很可能就是您请求的特定AWS服务(例如,iam
),非常感谢!!传递到getSignatureMethod的日期戳如何,它是否需要以与时间戳相同的格式(yyyy-MM-ddThh:MM:ssZ)传递?是的。ISO日期对于任何类型的数据交换都是非常必要的。它之所以被称为ISO,是因为它是国际标准组织的标准格式,几乎是唯一可以普遍理解的日期格式。看起来AWS希望签名为十六进制摘要。在C#中,您可以通过String.Concat(bytes.Select(b=>b.ToString(“X2”)).ToArray()来获得它。不确定这是否重要,但AWS示例签名都是小写的,因此您可能还需要调用ToLower
。