Получение Удаленный сервер возвратил ошибку: (403) Запрещено в C # во время вызова API с аутентификацией AWS - PullRequest
0 голосов
/ 14 ноября 2018

Получение HTTPResponse

"{\" message \ ": \" Рассчитанная нами подпись запроса не соответствует подпись вы предоставили. Проверьте свой секретный ключ доступа AWS и подпись метод. Обратитесь к сервисной документации для деталей. \ N \ nThe Каноническая строка для этого запроса должна иметь был \ n'GET \ п / постановка / пользователь \ nemail = тест% 40gmail.com & мобильный = 123 \ naccess-ID: dffgdfgfgdfg \ nhost: dfgdfgdfgf \ ой-AMZ-дата: 20181113T134535Z \ ого-апи-ключ: \ N \ naccess -id, хозяин; х-АМЗ-дата, х-апи ключ \ "\ п \ NThe Строка для подписи должна иметь был \ n'AWS4-HMAC-SHA256 \ n20181113T134535Z \ n20181113 / ар-юго-восток-1 / выполнение-апи / aws4_request \ dfgdfgdfgdfgd '\ п \ "}"

Код: -

 using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Security.Cryptography;
    using System.Text;
    using System.Text.RegularExpressions;


    namespace Test.Old_App_Code
    {
        public class APICall
        {
            public string CheckUserID()
            {
                UMSConfig oUMSConfig = new UMSConfig();
                 oUMSConfig.AccessId = "";
                 oUMSConfig.ApiKey = "";
                 oUMSConfig.Host = "";
                 oUMSConfig.RegionName = "";
                 oUMSConfig.SecretKey = "";
                 oUMSConfig.ServerName = "";
             var authorization = new AwsHeaders(oUMSConfig, "/staging/user", "GET", "?email=test@gmail.com&mobile=123", "");
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
            WebRequest webRequest = WebRequest.Create("https://" + oUMSConfig.Host + "/staging/user?email=test@gmail.com&mobile=123");
            webRequest.Method = "GET";
            webRequest.ContentType = "application/json";
            webRequest.Headers.Add("X-Amz-date", DateTime.Now.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
            webRequest.Headers.Add("Authorization", authorization.Authorization);
            webRequest.Headers.Add("x-api-key", oUMSConfig.ApiKey);
            webRequest.Headers.Add("access-id", oUMSConfig.AccessId);

            webRequest.UseDefaultCredentials = true;
            webRequest.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
            var response = (HttpWebResponse)webRequest.GetResponse();
            var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();

            return "";

        }
    }

    public class AwsHeaders
    {
        public const string ENCRYPT_METHOD = "AWS4-HMAC-SHA256";

        public string Host { get; private set; }
        public string RequestUrl { get; private set; }
        public string Authorization { get; private set; }
        public IDictionary<string, string> AddtionalHeaders { get; set; }
        public DateTime Date { get; private set; }
        public DateTime DateVersion { get; set; }

        public AwsHeaders(UMSConfig _config, string canonicalURI, string method, string queryString, string bodyPayload)
        {
            //setup info to generate headers
            this.Host = _config.Host;

            //aws will check this time for prevent over 5 minutes delay request
            this.Date = DateTime.Now.ToUniversalTime();
            this.DateVersion = DateTime.Now.ToUniversalTime();

            //content headers key-val pair to add to HttpClient
            this.AddtionalHeaders = new Dictionary<string, string>();
            this.AddtionalHeaders.Add("access-id", _config.AccessId);
            this.AddtionalHeaders.Add("host", _config.Host);
            this.AddtionalHeaders.Add("x-amz-date", GetDateTimeString());
            this.AddtionalHeaders.Add("x-api-key", _config.ApiKey);

            //get HttpMethod name from enum
            string httpRequestMethod = method.ToString();

            //query string or body of request should be process then it should be empty string if it is null
            var parsedQueryString = string.IsNullOrEmpty(queryString) ? "" : EncodeQueryString(queryString); //percent encode
            bodyPayload = string.IsNullOrEmpty(bodyPayload) ? "" : bodyPayload;

            //canonical headers are string combine of header-key:value+"\n" sorted by header key follow ASCII code
            string canonicalHeaders = string.Join("\n", this.AddtionalHeaders.Select(a => a.Key + ":" + a.Value)) + "\n";

            //signed headers are string combine of header-key join by "\n";
            string signedHeaders = string.Join(";", this.AddtionalHeaders.Select(a => a.Key));

            //hash the body by SHA256 then Encode it by Base16
            var sha256 = SHA256.Create();
            string hashPayload = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(bodyPayload))).Replace("-", "").ToLower();

            //Canonical Request is string combine of HttpRequestMethod, CanonicalURI, percent encoded QueryString, CanonicalHeaders, SignedHeaders and Body Payload - JOIN by "\n"
            //The canonical URI is the URI-encoded version of the absolute path component of the URI, which is everything in the URI from the HTTP host to the question mark character ("?") that begins the query string parameters (if any).
            string canonicalRequest = httpRequestMethod + "\n" + canonicalURI + "\n" + parsedQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashPayload;

            //Get Base16 encoded string of SHA256(CanonicalRequest)
            //Use for build the Authorization Header
            string hashedCanonicalRequest = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(canonicalRequest))).Replace("-", "").ToLower();

            //Use for build the Authorization Header
            string credentialScope = $"{GetDateVersionString()}/{_config.RegionName}/{_config.ServerName}/aws4_request";

            //Use for build Signature
            string stringToSign = AwsHeaders.ENCRYPT_METHOD + '\n'
                           + GetDateTimeString() + '\n'
                           + credentialScope + '\n' + hashedCanonicalRequest;

            //transfer secretkey to derived signing key for security
            byte[] derivedSigningKey = GetSignatureKey(_config.SecretKey, GetDateVersionString(), _config.RegionName, _config.ServerName);

            //Get final Signature
            string signature = BitConverter.ToString(HmacSHA256(stringToSign, derivedSigningKey)).Replace("-", "").ToLower();

            string authorizationHeader = "Credential=" + _config.AccessId + "/" + credentialScope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature;

            this.Authorization = AwsHeaders.ENCRYPT_METHOD + " " + authorizationHeader; //new AuthenticationHeaderValue(AwsHeaders.ENCRYPT_METHOD, authorizationHeader);

            this.RequestUrl = $"{UMSConfig.HTTP_SCHEME}{_config.Host}{canonicalURI}";
            if (!string.IsNullOrEmpty(queryString))
            {
                this.RequestUrl += $"?{queryString}";
            }
        }

        private byte[] HmacSHA256(string data, byte[] key)
        {
            var hasher = new HMACSHA256(key);
            return hasher.ComputeHash(Encoding.UTF8.GetBytes(data));
        }

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

        private string EncodeQueryString(string query)
        {
            var keysVals = query.Split('&');
            IDictionary<string, string> queries = new Dictionary<string, string>();
            foreach (var kv in keysVals)
            {
                var splits = kv.Split('=');
                var key = splits[0];
                var val = splits[1];
                if (!string.IsNullOrEmpty(val))
                {
                    val = Uri.EscapeDataString(val);
                }
                queries.Add(key, val);
            }

            var encodedQuery = EncodeSpecialCharacters(string.Join("&", queries.OrderBy(q => q.Key).Select(v => Uri.EscapeDataString(v.Key) + (!string.IsNullOrEmpty(v.Value) ? "=" + v.Value : ""))));

            return encodedQuery;
        }

        private string EncodeSpecialCharacters(string data)
        {
            //Do not URI-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ )
            if (data.Contains("!"))
                data = data.Replace("!", "%21");
            if (data.Contains("'"))
                data = data.Replace("'", "%27");
            if (data.Contains("("))
                data = data.Replace("(", "%28");
            if (data.Contains(")"))
                data = data.Replace(")", "%29");
            if (data.Contains("*"))
                data = data.Replace("*", "%2A");
            if (data.Contains(","))
                data = data.Replace(",", "%2C");

            return data;
        }

        public string GetDateTimeString()
        {
            return this.Date.ToString("yyyyMMddTHHmmssZ");
        }

        public string GetDateVersionString()
        {
            return this.DateVersion.ToString("yyyyMMdd");
        }
    }

    public class UMSConfig
    {
        public const string HTTP_SCHEME = "https://";

        public string Host { get; set; }
        public string Environment { get; set; }
        public string AccessId { get; set; }
        public string SecretKey { get; set; }
        public string RegionName { get; set; }
        public string ServerName { get; set; }
        public string ApiKey { get; set; }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...