Ошибка аутентификации при получении файла с использованием файловой службы REST API Azure - PullRequest
0 голосов
/ 05 марта 2020

Я пытаюсь получить файл, используя общий ключ. Я уже получаю список файлов и каталогов по общему ключу, но когда я запрашиваю получение указанного c файла, я сталкиваюсь с этой проблемой.

Код для генерации общего ключа:

using System;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace StorageRestApiAuth
{

    internal static class AzureStorageAuthenticationHelper
    {
        internal static AuthenticationHeaderValue GetAuthorizationHeader(
           string storageAccountName, string storageAccountKey, DateTime now,
           HttpRequestMessage httpRequestMessage, string ifMatch = "", string md5 = "")
        {
            // This is the raw representation of the message signature.
            HttpMethod method = httpRequestMessage.Method;
            String MessageSignature = String.Format("{0}\n\n\n{1}\n{5}\n\n\n\n{2}\n\n\n\n{3}{4}",
                      method.ToString(),
                      (method == HttpMethod.Get || method == HttpMethod.Head) ? String.Empty
                        : httpRequestMessage.Content.Headers.ContentLength.ToString(),
                      ifMatch,
                      GetCanonicalizedHeaders(httpRequestMessage),
                      GetCanonicalizedResource(httpRequestMessage.RequestUri, storageAccountName),
                      md5);

            byte[] SignatureBytes = Encoding.UTF8.GetBytes(MessageSignature);

            HMACSHA256 SHA256 = new HMACSHA256(Convert.FromBase64String(storageAccountKey));

            string signature = Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
returned.
            AuthenticationHeaderValue authHV = new AuthenticationHeaderValue("SharedKey",
                storageAccountName + ":" + Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes)));
            return authHV;
        }

        private static string GetCanonicalizedHeaders(HttpRequestMessage httpRequestMessage)
        {
            var headers = from kvp in httpRequestMessage.Headers
                          where kvp.Key.StartsWith("x-ms-", StringComparison.OrdinalIgnoreCase)
                          orderby kvp.Key
                          select new { Key = kvp.Key.ToLowerInvariant(), kvp.Value };

            StringBuilder sb = new StringBuilder();

            foreach (var kvp in headers)
            {
                StringBuilder headerBuilder = new StringBuilder(kvp.Key);
                char separator = ':';

                foreach (string headerValues in kvp.Value)
                {
                    string trimmedValue = headerValues.TrimStart().Replace("\r\n", String.Empty);
                    headerBuilder.Append(separator).Append(trimmedValue);

                    separator = ',';
                }
                sb.Append(headerBuilder.ToString()).Append("\n");
            }
            return sb.ToString();
        }      

        private static string GetCanonicalizedResource(Uri address, string storageAccountName)
        {
            StringBuilder sb = new StringBuilder("/").Append(storageAccountName).Append(address.AbsolutePath);

            NameValueCollection values = HttpUtility.ParseQueryString(address.Query);

            foreach (var item in values.AllKeys.OrderBy(k => k))
            {
                sb.Append('\n').Append(item).Append(':').Append(values[item]);
            }

            return sb.ToString().ToLower();

        }
    }
}

С помощью этого кода я могу получить список каталогов и файлов, но не могу получить указанный c файл. Я использую этот URL для запроса: https://myaccount.file.core.windows.net/myshare/mydirectorypath/myfile Ошибка отправки запроса:

{
    "Error": {
        "Code": "AuthenticationFailed",
        "Message": "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:4c9ca5be-301a-0045-29c9-f20135000000\nTime:2020-03-05T08:36:05.9908405Z",
        "AuthenticationErrorDetail": "The MAC signature found in the HTTP request 'here is my key' is not the same as any computed signature. Server used following string to sign: 'GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Thu, 05 Mar 2020 08:36:05 GMT\nx-ms-version:2017-04-17\n/my storage account/my share/myfile.JPG'."
    }
}

1 Ответ

1 голос
/ 06 марта 2020

Я тестирую на своем сайте ваш код, и он работает хорошо. С вашим AzureStorageAuthenticationHelper и вот его следующий код, который я получаю содержимое файла.

static void Main(string[] args)
{
    GetFileContentAsyncREST("youraccount", "yourkey", CancellationToken.None).GetAwaiter().GetResult();

    Console.WriteLine("Press any key to continue.");
    Console.ReadLine();
}

private static async Task GetFileContentAsyncREST(string storageAccountName, string storageAccountKey, CancellationToken cancellationToken)
{
    string uri = "https://xxxxx.file.core.windows.net/helloworld/directory/helloworld.txt";
    Byte[] requestPayload = null;

    using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri)
    { 
        Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
        {
            DateTime now = DateTime.UtcNow;
            httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
            httpRequestMessage.Headers.Add("x-ms-version", "2017-04-17");
            httpRequestMessage.Headers.Authorization = AzureStorageAuthenticationHelper.GetAuthorizationHeader(
                   storageAccountName, storageAccountKey, now, httpRequestMessage);

            using (HttpResponseMessage httpResponseMessage = await new HttpClient().SendAsync(httpRequestMessage, cancellationToken))
            {
                if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
                {
                    string content = await httpResponseMessage.Content.ReadAsStringAsync();
                    Console.Write(content);
                }
            }
        }
    }
}

Для получения более подробной информации, вы можете обратиться к этому api остальной памяти с образца аутентификации .

...