【问题标题】:Azure Blob Storage REST API signatureAzure Blob 存储 REST API 签名
【发布时间】:2017-09-29 16:06:10
【问题描述】:

我一直致力于概念验证,并希望针对 Azure 存储 REST API 进行测试。但是,我无法进行身份验证。我已经尝试了一整天的阅读、调整和重写,但它仍然不起作用。我已经逐步完成了文档。

我希望找到能解决这个问题的人。很多硬编码位,只是为了让它工作。我不断收到此错误作为回应

在 HTTP 请求 '' 中找到的 MAC 签名与任何计算的签名都不相同

谁能看到我的脸可能在盯着我看?快把我逼疯了。

    var requestDateString = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
    var StorageAccountName = "<account removed>";
    var StorageKey = "<key removed>";

    using (var client = new HttpClient())
    {
        var stringToSign = new List<string>(){
        "GET"                                                                                               /*HTTP Verb*/  
        ,""                                                                                                 /*Content-Encoding*/  
        ,""                                                                                                 /*Content-Language*/  
        ,""                                                                                            /*Content-Length (include value when zero)*/  
        ,""                                                                                                 /*Content-MD5*/  
        ,""                                                                                                 /*Content-Type*/  
        ,""                                                                                                 /*Date*/  
        ,""                                                                                                 /*If-Modified-Since */  
        ,""                                                                                                 /*If-Match*/  
        ,""                                                                                                 /*If-None-Match*/  
        ,""                                                                                                 /*If-Unmodified-Since*/  
        ,""                                                                                                 /*Range*/  
        ,$"x-ms-date:{requestDateString}\nx-ms-version:2015-02-21"                                          /*CanonicalizedHeaders*/
        ,$"/{StorageAccountName}/ " + _containerName + "\ncomp:metadata\nrestype:container\ntimeout:20"     /*CanonicalizedResource*/
        };


        string signature;
        using (var hmac = new HMACSHA256(Convert.FromBase64String(StorageKey)))
        {
            var compiledStringToSign = (string.Join("\n", stringToSign));
            byte[] dataToHmac = Encoding.UTF8.GetBytes(compiledStringToSign);
            signature = Convert.ToBase64String(hmac.ComputeHash(dataToHmac));
        }

        //Send Request
        client.DefaultRequestHeaders.Add("x-ms-date", requestDateString);
        client.DefaultRequestHeaders.Add("x-ms-version", " 2015-02-21");
        client.DefaultRequestHeaders.Add("Authorization", $"SharedKey {StorageAccountName}:" + signature);

        var response = client.SendAsync(request);

//编辑 请求网址为https://account.blob.core.windows.net/testcontainer/blobtest/blob1234

该错误非常具体地表明身份验证失败,所以我认为错误必须在签名中,但我真的看不到它。我用提琴手检查了所有输出以确保它们匹配

【问题讨论】:

  • 请问您为什么不使用 Azure Storage SDK for C#?
  • 我曾经在没有 SDK 的时候用 Python 实现过这个。 AFAIK C# SDK 在 GitHub 上是开源的,您可以查看代码 - 两年前我发现该实现非常易读
  • 您也可以分享请求网址吗?
  • 我已经使用 SDK,但想看看我是否可以通过 REST API 获得更好的速度。 SDK 在第一次请求时会进行 500-1000 毫秒的“预热”。如果您运行一个测试应用程序并单独下载 10 张图像,首先是 500 毫秒,其余是 50 毫秒。我用 MS 记录了它,但他们说它的 SDK 缓存和设计。对于 Web 应用程序,每个请求都像第一次运行一样,所以它可能会有点慢。希望使用 REST API 可以绕过这一点。

标签: azure azure-storage restful-authentication


【解决方案1】:

如果您想获取blob内容,请尝试使用以下演示代码,它在我这边可以正常工作。

var blobStorageAccount = "account name";
var storageKey = "account key";
var containerName = "container name";
var requestMethod = "GET";
var blobName = "blob name"; // in your case:blobtest/blob1234
var dt = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
var msVersion = "2015-02-21";
var clientRequestId = Guid.NewGuid().ToString();
var canHeaders = $"x-ms-client-request-id:{clientRequestId}\nx-ms-date:{dt}\nx-ms-version:{msVersion}";
var canResource = $"/{blobStorageAccount}/{containerName}/{blobName}"; //not the CanonicalizedResource : /myaccount/mycontainer\ncomp:metadata\nrestype:container\ntimeout:20
var signStr = $"{requestMethod}\n\n\n\n\n\n\n\n\n\n\n\n{canHeaders}\n{canResource}";
var auth = CreateAuthString(blobStorageAccount, signStr, storageKey);
var urlPath = $"https://{blobStorageAccount}.blob.core.windows.net/{containerName}/{blobName}";
Uri uri = new Uri(urlPath);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("x-ms-date", dt);
client.DefaultRequestHeaders.Add("x-ms-version", msVersion);
client.DefaultRequestHeaders.Add("x-ms-client-request-id", clientRequestId);
client.DefaultRequestHeaders.Add("Authorization", auth);
HttpResponseMessage response = client.SendAsync(request).Result;
var status =  response.IsSuccessStatusCode;


private static string CreateAuthString(string blobStorageAccount,string signStr,string blobStorageAccessKey)
{
   var signature = string.Empty;
   byte[] unicodeKey = Convert.FromBase64String(blobStorageAccessKey);
   using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
   {
      byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(signStr);
      signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
   }

     var authorizationHeader = String.Format(
         CultureInfo.InvariantCulture,
         "{0} {1}:{2}",
         "SharedKey",
         blobStorageAccount,
         signature);

       return authorizationHeader;
  }

【讨论】:

  • 这行得通,canonicalizedResource 更改是需要的。我能问一下您从哪里获得的信息,因为它与 Azure 文档不匹配
  • 看来是文档问题,根据Get blob APImyaccount.blob.core.windows.net/mycontainer/myblob,我假设canonicalizedResource应该是$"/{blobStorageAccount}/{containerName}/{blobName}"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 2021-10-13
  • 2019-08-09
  • 2019-11-08
  • 2017-02-09
  • 1970-01-01
相关资源
最近更新 更多