【问题标题】:Amazon API generating a request signature in C# .NETAmazon API 在 C# .NET 中生成请求签名
【发布时间】:2017-05-03 14:43:03
【问题描述】:

我试图弄清楚如何在我的 .NET 应用程序中传递参数。 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]

我感到困惑的部分是:

 &Timestamp=[YYYY-MM-DDThh:mm:ssZ]
      &Signature=[Request_Signature]

我不确定我是否可以简单地为时间戳部分做这样的事情:

var TimeStamp  = DateTime.Now; // without any special datetime formating? 

所以我的问题是如何在请求 URL 中实际生成此签名 URL?

我拥有以上所有这些参数,但我不确定如何生成最后一个?

有人可以帮帮我吗?

【问题讨论】:

  • 有人吗??有什么建议吗?

标签: c# asp.net asp.net-mvc amazon-web-services c#-4.0


【解决方案1】:

AWS 使用 HMAC 请求签名。一般来说,它的工作方式是您创建一个“消息”,它由您的访问密钥、请求标头、请求正文和时间戳等内容组成。然后你 HMAC 这个“消息”,它成为你请求的“签名”。这可以防止重放攻击,因为每个请求都必须具有唯一的签名。

看起来时间戳只需要采用 ISO 格式 (YYYY-MM-DDThh:mm:ssZ),所以,不,您不能只使用 DateTime.NowToString 使用的默认格式不是 ISO。相反,你需要使用类似的东西:

DateTime.Now.ToString("yyyy-MM-ddThh:mm:sszzz");

或者实际上使用 UTC 时间并简单地附加一个 Z 可能会更好:

DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ");

至于创建签名,请参阅AWS documentation,他们提供了一些示例代码:

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;
}

【讨论】:

  • 克里斯哇非常感谢!!!我找到了这段代码,但我仍然对参数的“RegionName”和“ServiceName”部分感到困惑,我需要在该部分输入什么??
  • 这是 AWS 特定的东西,但我相信它们指的是您所在的区域,因为 AWS 等云服务通常是特定于区域的 (east-us-1)。无论你在做什么,都会去那里。该服务可能是您向其发出请求的特定 AWS 服务(例如 iam
  • 很棒的克里斯非常感谢!!那么传入getSignatureMethod的dateStamp呢,是否需要和timestamp(yyyy-MM-ddThh:mm:ssZ)一样的格式传入?
  • 是的。 ISO 日期对于任何类型的数据交换都是非常必要的。之所以称为 ISO,是因为它是国际标准化组织的标准格式,并且几乎是唯一可以普遍理解的日期格式。
  • 看起来 AWS 希望将签名作为十六进制摘要。在 C# 中,您可以通过 String.Concat(bytes.Select(b => b.ToString("X2")).ToArray()) 获得。不确定是否重要,但 AWS 示例签名都是小写的,因此您可能还需要调用 ToLower
【解决方案2】:
/*

    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 这肯定是不正确的。如果您没有传递区域参数,亚马逊如何创建相同的签名,因为它没有所有信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 2018-10-11
    相关资源
    最近更新 更多