0

我正在尝试使用共享密钥获取文件。我已经通过共享密钥获得了文件和目录的列表,但是当我请求接收特定文件时,我遇到了这个问题。

生成共享密钥的代码:

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();

        }
    }
}

使用此代码,我可以获得目录和文件的列表,但无法获得特定文件。我正在使用此 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'."
    }
}
4

1 回答 1

1

我用你的代码在我的网站上进行了测试,它运行良好。使用您的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);
                }
            }
        }
    }
}

有关更多详细信息,您可以参考此storage rest api with auth sample

于 2020-03-06T09:37:14.627 回答