1

我希望通过从 VB.NET 程序发送一个(概念上)包含图书 ISBN 号的简单请求,从亚马逊网络服务(AWS)产品广告 API 检索图书详细信息(以 XML 格式)。我有一个带有 AWS 访问密钥和密钥的 Amazon AWS 账户。

我可以进入访问 AWS 的阶段,但得到以下响应:

  <?xml version="1.0"?>
  <ItemLookupErrorResponse xmlns="http://ecs.amazonaws.com/doc/2005-10-05/">
  <Error><Code>SignatureDoesNotMatch</Code><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></Error>
  <RequestId>556dafef-b59f-4829-8ffe-80668cea9707</RequestId>
  </ItemLookupErrorResponse>

我正在使用的代码如下(这里真正的访问密钥和秘密密钥已被虚拟字符串替换):

Public Shared Function MakeRequestString(IsbnString As String) As String

    Dim stringToSign, strTimestamp, strSignature, strSignedRequest, strParamValuePairs As String

    stringToSign = "GET" & vbLf   'vbLf is Line feed character Ascii 10

    stringToSign &= "webservices.amazon.com" & vbLf

    stringToSign &= "/onca/xml" & vbLf

    '-----------------------------------------------------------------------

    strParamValuePairs = "AWSAccessKeyId=" & GetAWSAccessKey()

    strParamValuePairs &= "&IdType=ISBN"

    strParamValuePairs &= "&ItemId=" & IsbnString

    strParamValuePairs &= "&Operation=ItemLookup"

    strParamValuePairs &= "&Service=AWSECommerceService"

    strTimestamp = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fff")

    strParamValuePairs &= "&Timestamp=" & UrlEncode(strTimestamp)

    stringToSign = stringToSign & strParamValuePairs

    '---------------------------------------------------------------
    strSignature = MakeSignature(stringToSign)
   '----------------------------------------------------

    strSignedRequest = "http://webservices.amazon.com/onca/xml?"

    strSignedRequest &= "AWSAccessKeyId=" & GetAWSAccessKey()

    strSignedRequest &= "&IdType=ISBN"

    strSignedRequest &= "&ItemId=" & IsbnString

    strSignedRequest &= "&Operation=ItemLookup"

    strSignedRequest &= "&Service=AWSECommerceService"

    strSignedRequest &= "&Signature=" & UrlEncode(strSignature)

    strSignedRequest &= "&Timestamp=" & UrlEncode(strTimestamp)

    Return strSignedRequest

End Function


Private Shared Function MakeSignature(ByVal StringToHash As String) As String

    Dim myEncoder As New System.Text.UTF8Encoding

    Dim strSecretAccessKey As String = GetSecretKey()

    Dim Key As Byte() = myEncoder.GetBytes(strSecretAccessKey)

    Dim bytStringToHashAsBytes As Byte() = myEncoder.GetBytes(StringToHash)

    Dim myHMACSHA256 As New System.Security.Cryptography.HMACSHA256(Key)

    Dim HashCode As Byte() = myHMACSHA256.ComputeHash(bytStringToHashAsBytes)

    Return Convert.ToBase64String(HashCode)

End Function


Private Shared Function GetSecretKey() As String

    Return "AAAAAAA Secret Key AAAAAAA"

End Function


Private Shared Function GetAWSAccessKey() As String

    Return "AAAA Access Key AAAAA"

End Function

为了组装上述代码,我遵循了亚马逊 AWS 产品广告 API 开发人员指南示例休息请求 ( http://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html )

请注意,在生成签名后的这些指南(步骤 9)中,说明是对签名中的加号 (+) 和等号 (=) 字符进行 URL 编码,然后在签名请求中包含这样的 URL 编码签名 - 但是在他们在指南中使用的示例他们似乎对签名中的其他字符进行 URL 编码,例如正斜杠字符。我已经尝试过 URL 编码,但无济于事。

至于 URL 编码,一些参数不包含任何可能有问题的字符,这包括 AWS 访问密钥。Timestamp 包含 - 和 : 字符,Secret 密钥中似乎总是有一个正斜杠 (/) 字符。计算出的签名将包含特殊字符。

我注意到,如果您在时间戳中包含空格,则请求不会进入返回 AWS 错误的阶段,而是无法找到网页的错误(因此时间戳中的日期和时间之间的 T) .

4

0 回答 0