从 API 身份验证返回的 Azure Blob SAS 网址失败 .net 核心

Posted

技术标签:

【中文标题】从 API 身份验证返回的 Azure Blob SAS 网址失败 .net 核心【英文标题】:Azure Blob SAS Url returned from API authentication failed .net core 【发布时间】:2021-09-19 16:17:56 【问题描述】:

我正在尝试将 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 解码是因为我在*** 上看到了一个类似的问题,他们谈到了双重编码。

但是,当我将此 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>

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

<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

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

【问题讨论】:

【参考方案1】:

请在此处从Path 中删除files

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 令牌是针对不同路径获取的,但用于其他路径,因此您会收到错误消息。

【讨论】:

嗨 Gaurav 感谢您的回复,我正在寻找的 blob 位于容器文件下,是否仍应将其删除?这不会使 URL 无效,因为它找不到资源 您的意思是说您的容器名称是files?答案是不。基本上你的路径将是container-name/blob-name,所以它应该保留在那里。 抱歉让您感到困惑,在这种情况下,容器名称不是一个不同的值,一个唯一的 ID,但所有这些都存储在一个名为 files 的通用容器下。因为我们在那里存储的是公司文件。我将在我的问题上发布屏幕截图以澄清结构 我已经上传了屏幕截图,显然 containerName/blobName 在这种情况下的屏幕截图将解析为 bqXbY54sRRsipOUB1PF6/fyI67FYOqDS80y1vNWRL/PRE_OP_CT/0/TK1.left.TST.PTN1.PRE_OP_CT.zip 之类的东西为什么我添加了文件/那里 :)。你应该早点来这里。很高兴听到您的问题得到解决。

以上是关于从 API 身份验证返回的 Azure Blob SAS 网址失败 .net 核心的主要内容,如果未能解决你的问题,请参考以下文章

在 Azure 存储 [REST] [Azure Blob] 中对 PUT Blob 的 REST api 调用中的身份验证失败

使用 Azure Ad Auth 从 .NET Core Web API 读取/写入 Azure Blob

可以将 hadoop-azure 配置为对 azure blob 使用活动目录(租户、appId、appSecret)身份验证吗

尝试在 Web API 请求上检索 Azure Blob 时出现 403 错误

如何向 Azure 存储 Blob 上传添加身份验证

无需身份验证即可访问 Azure Blob 文件