首页 > 解决方案 > 从 API 身份验证返回的 Azure Blob SAS Url 失败 .net 核心

问题描述

我正在尝试将 SAS url 返回到我的前端,以便我可以将用户重定向到该链接,以便他们可以下载文件。

这是我创建 SAS url 的代码

   private SasQueryParameters GenerateSaSCredentials(string containerName, string blobName) {


        //  Defines the resource being accessed and for how long the access is allowed.
        BlobSasBuilder blobSasBuilder = new() {
            StartsOn = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(10)),
            ExpiresOn = DateTime.UtcNow.Add(TimeSpan.FromMinutes(120)) + TimeSpan.FromSeconds(1),
            Resource = "b",
            BlobName = blobName,
            BlobContainerName = containerName
        };
        
        //  Defines the type of permission.
        blobSasBuilder.SetPermissions(BlobSasPermissions.Read);

        //  Builds an instance of StorageSharedKeyCredential      
        StorageSharedKeyCredential storageSharedKeyCredential = new(_accountName, _key);

        //  Builds the Sas URI.
        return blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential);
    }

    public Uri CreateBlobUri(string blobName, string containerName) {
        SasQueryParameters parameters = GenerateSaSCredentials(containerName, blobName);
        
        return new UriBuilder {
            Scheme = "https",
            Host = $"{_accountName}.blob.core.windows.net",
            Path = $"files/{containerName}/{blobName}",
            Query = WebUtility.UrlDecode(parameters.ToString())
        }.Uri;
        
    }

您可能会注意到 parameters.ToString() 上的 url 解码是因为我在 stackoverflow 上看到了类似的问题,他们谈到了双重编码。

但是,当我将此 url 返回到浏览器并重定向时,我收到以下错误。

这就是我返回 URL 的方式

 return Ok(_blobUtils.CreateBlobUri(fileName, containerName).ToString());

<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header 
  is formed correctly including the signature. RequestId:01696cca-d01e-0023-2ea4-74f5df000000 
  Time:2021-07-09T09:23:33.0250817Z</Message>
  <AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
</Error>

如果我从中删除 WebUtility.UrlDecode parameters.ToString(),我会收到此错误

<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header 
  is formed correctly including the signature. RequestId:016a1821-d01e-0023-3da4-74f5df000000 
  Time:2021-07-09T09:24:38.4051042Z</Message>
  <AuthenticationErrorDetail>Signature did not match. String to sign used was r 2021-07- 
 09T09:14:38Z 2021-07-09T11:24:39Z /blob/${_acountName}/files/bqXbY54sRRsipOUB1PF6/fyI67FYOqDS80y1vNWRL/PRE_OP_CT/0/TK1.left.TST.PTN1.PRE 
 _OP_CT.zip 2020-04-08 b </AuthenticationErrorDetail>
</Error>

我试图访问的 Blob 的结构是:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 最后是我们试图创建一个 SAS 的 blob

在此处输入图像描述

谁能明白为什么这会失败?

标签: c#azure.net-coreazure-blob-storage

解决方案


files请从Path这里摆脱:

return new UriBuilder {
    Scheme = "https",
    Host = $"{_accountName}.blob.core.windows.net",
    Path = $"files/{containerName}/{blobName}",
    Query = WebUtility.UrlDecode(parameters.ToString())
}.Uri;

它应该是这样的:

return new UriBuilder {
    Scheme = "https",
    Host = $"{_accountName}.blob.core.windows.net",
    Path = $"{containerName}/{blobName}",
    Query = WebUtility.UrlDecode(parameters.ToString())
}.Uri;

更新

根据屏幕截图和错误消息,您的容器files名称为 ,blob 名称为bqXbY54sRRsipOUB1PF6/fyI67FYOqDS80y1vNWRL/PRE_OP_CT/0/TK1.left.TST.PTN1.PRE. 请在您的代码中使用它们,您应该不会收到错误消息。您仍然需要files从上面的路径中删除,因为它已经包含在您的containerName.

您的代码失败的原因是因为您正在为 blob 容器内的 blob 计算 SAS 令牌(blob 路径变为container-name/blob-name)。但是,在您的请求中,您在files请求 URL 之前,您的 blob 路径变为files/container-name/blob-name. 由于 SAS 令牌是针对不同路径获取的,但用于其他路径,因此您会收到错误消息。


推荐阅读