2

AWS フォーラムで質問しましたが、多くの意見が寄せられましたが、コメントはありません。

こんにちは、topsites サービスを呼び出す単純な C# コンソール アプリケーションを 2 日間書き込もうとしましたが、まだ署名生成で問題が発生しています。

ギャラリーの Java サンプルを使用してテストしたところ、アクセスキー ID とシークレットを使用して正常にクエリを実行できました。次に、C# コードを使用して同じ署名を生成できることを証明しましたが、コードはそうしますが、リクエストを作成して API に対して発行すると、すべてのリクエストが 403 ステータスを返します - signaturedoesnotmatch - 誰か助けてください私は問題が何であるかを見つけますか?私はこれで髪を引き裂いています。

C# コード:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace ConsoleApplication1
{
    class Program
    {
        private static string baseUrl = ConfigurationManager.AppSettings["baseUrl"];
        private static string accessKeyId = ConfigurationManager.AppSettings["accessKeyId"];
        private static string accessKey = ConfigurationManager.AppSettings["accessKey"];
        private static string serviceVersion = ConfigurationManager.AppSettings["serviceVersion"];
        static void Main(string[] args)
        {
            HttpClient client = new HttpClient();
            string requestParameters = "AWSAccessKeyId=" + accessKeyId + "&Action=TopSites&Count=10&CountryCode=&ResponseGroup=Country&SignatureMethod=HmacSHA256&SignatureVersion=2&Start=1001&Timestamp=" + Amazon.Util.AWSSDKUtils.FormattedCurrentTimestampISO8601;
            var signature = generateSignature(requestParameters);
            var url = "http://" + baseUrl + "?" + requestParameters + "&Signature=" + signature;
            HttpResponseMessage message = client.GetAsync(url).Result;

            Console.ReadKey();
        }
        private static string generateSignature(string queryParameters)
        {
            string stringToSign = "GET\n" + baseUrl + "\n/\n" + queryParameters;
            var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
            var secretKeyBytes = Encoding.UTF8.GetBytes(accessKey);
            var hmacSha256 = new HMACSHA256(secretKeyBytes);
            var hashBytes = hmacSha256.ComputeHash(bytesToSign);
            var signature = System.Net.WebUtility.UrlEncode(Convert.ToBase64String(hmacSha256.Hash));
            Trace.Write("String to sign:{0}", signature);
            return signature;
        }
    }
}

生成されたリクエスト (Fiddler から): GET http://ats.amazonaws.com/?AWSAccessKeyId=REMOVED&Action=TopSites&Count=10&CountryCode=&ResponseGroup=Country&SignatureMethod=HmacSHA256&SignatureVersion=2&Start=1001&Timestamp=2014-11-20T16:57:52.422Z&Signature=vdKOQYRmoJJzL3GecolimGAXY9% 3D HTTP/1.1 ホスト: ats.amazonaws.com 接続: キープアライブ

Response: HTTP/1.1 403 Forbidden Server: Apache-Coyote/1.1 Transfer-Encoding: chunked Date: Thu, 20 Nov 2014 16:57:52 GMT

16d SignatureDoesNotMatch計算したリクエストの署名が、提供された署名と一致しません。AWS シークレット アクセス キーと署名方法を確認します。詳細については、サービス ドキュメントを参照してください。84291dc8-a35e-7dc3-7cc1-56fe20b5b236 0

4

1 に答える 1

0

Darrel のコメントと、Java アプリと私のサンプル アプリからのリクエストの広範な比較に基づいて、上記のサンプルを含む多くのリクエストを使用して、サービスを正しくクエリすることができました。署名されたリクエスト文字列のホスト名の前に誤ったスペース文字が含まれていたことが問題だったようですエンコーディングは正しいです。

作業サンプルコードは次のとおりです。

using System;
using System.Configuration;
using System.Diagnostics;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;   

namespace ConsoleApplication1
{
    class Program
    {
        private static string baseUrl = ConfigurationManager.AppSettings["AlexaServiceUrl"];
        private static string accessKeyId = ConfigurationManager.AppSettings["AlexaAccessKeyId"];
        private static string accessKey = ConfigurationManager.AppSettings["AlexaAccessKey"];
        private static string serviceVersion = ConfigurationManager.AppSettings["AlexaServiceVersion"];
        static void Main(string[] args)
        {
            HttpClient client = new HttpClient();
            string requestParameters = "AWSAccessKeyId=" + accessKeyId + "&Action=TopSites&Count=10&CountryCode=&ResponseGroup=Country&SignatureMethod=HmacSHA256&SignatureVersion=2&Start=1001&Timestamp=" + Amazon.Util.AWSSDKUtils.UrlEncode(Amazon.Util.AWSSDKUtils.FormattedCurrentTimestampISO8601, false);
            var signature = generateSignature(requestParameters);
            var url = "http://" + baseUrl + "/?" + requestParameters + "&Signature=" + signature;
            HttpResponseMessage message = client.GetAsync(url).Result;

            Console.ReadKey();
        }
        private static string generateSignature(string queryParameters)
        {
            string stringToSign = String.Format("GET{0}{1}{2}/{3}{4}", "\n", baseUrl, "\n", "\n", queryParameters);
            var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
            var secretKeyBytes = Encoding.UTF8.GetBytes(accessKey);
            var hmacSha256 = new HMACSHA256(secretKeyBytes);
            var hashBytes = hmacSha256.ComputeHash(bytesToSign);
            var signature = Amazon.Util.AWSSDKUtils.UrlEncode(Convert.ToBase64String(hmacSha256.Hash), false);
            Trace.Write("String to sign:{0}", signature);
            return signature;
        }
    }
}

これが他の誰かにも役立つことを願っています。

于 2014-11-25T18:00:58.363 に答える