VB.NET プログラムから書籍の ISBN 番号を含む (概念的には) シンプルなリクエストを送信することで、アマゾン ウェブ サービス (AWS) Product Advertising 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
上記のコードを組み立てるために、Amazon AWS Product Advertising API Developer Guide Example Rest Requests ( http://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html )に従いました。
これらのガイドライン (ステップ 9) では、署名を生成した後、署名内のプラス (+) 文字と等号 (=) 文字を URL エンコードし、そのような URL エンコードされた署名を署名付き要求に含めるように指示されていることに注意してください。彼らがガイドラインで使用している例では、スラッシュ文字などの署名内の他の文字を URL エンコードしているようです。URL エンコーディングを試してみましたが、役に立ちませんでした。
URL エンコーディングに関しては、一部のパラメータには潜在的に問題のある文字が含まれていません。これには AWS アクセス キーが含まれます。タイムスタンプには - と : の文字が含まれており、秘密鍵には常にスラッシュ (/) 文字が含まれているようです。計算された署名には特殊文字が含まれます。
タイムスタンプにスペースを含めると、リクエストは AWS エラーを返す段階に進まず、ウェブページが見つからないというエラーになります (したがって、タイムスタンプの日付と時刻の間の T)。 .