You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BlobSasBuilder生成的Azure SAS URI签名无效问题排查

问题:生成Azure存储容器User Delegation SAS时出现签名不匹配错误

我编写了一个方法来返回Azure存储容器的SAS URI,代码运行正常且生成的URI格式看似有效,但使用时出现如下错误:

<?xml version="1.0" encoding="utf-8"?>
<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:bdfae000-901e-00e2-093a-87e256000000
        Time:2024-04-05T09:19:45.7818447Z
    </Message>
    <AuthenticationErrorDetail>
        Signature did not match. String to sign used was rl
        2024-04-06T09:19:24Z
        /blob/tmfootballdev/$root
        b066bc3e-48c7-42d6-a041-9b900744166f
        eb272a1e-e767-4041-9363-f8736579f898
        2024-04-05T09:04:15Z
        2024-04-06T09:19:15Z
        b
        2023-11-03
        https
        2023-11-03
        c
    </AuthenticationErrorDetail>
</Error>

我通过以下代码生成User Delegation SAS:

public async Task<Uri> GetContainerSas(BlobContainerClient containerClient)
{
    // Construct the blob endpoint from the account name.
    string endpoint = $"https://{_accountName}.blob.core.windows.net";

    // Create a blob service client object using DefaultAzureCredential
    BlobServiceClient blobServiceClient = new(
        new Uri(endpoint),
        new DefaultAzureCredential());

    // Get a user delegation key for the Blob service that's valid for 1 day
    UserDelegationKey userDelegationKey =
        await blobServiceClient.GetUserDelegationKeyAsync(
            DateTimeOffset.UtcNow.AddMinutes(-15),
            DateTimeOffset.UtcNow.AddDays(1));

    // Create a SAS token for the blob resource that's also valid for 1 day
    BlobSasBuilder sasBuilder = new()
    {
        BlobContainerName = containerClient.Name,
        Resource = "c",
        ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
        Protocol = SasProtocol.Https
    };

    // Specify the necessary permissions
    sasBuilder.SetPermissions(
        BlobSasPermissions.List | BlobSasPermissions.Read);


    // Add the SAS token to the blob URI
    BlobUriBuilder uriBuilder = new(containerClient.Uri)
    {
        // Specify the user delegation key
        Sas = sasBuilder.ToSasQueryParameters(
            userDelegationKey,
            containerClient.AccountName)
    };

    return uriBuilder.ToUri();
}

代码基于微软官方文档修改,适配容器级而非单个Blob。生成的无效SAS URI示例(签名已隐藏):

https://<account>.blob.core.windows.net/test
?skoid=b066bc3e-48c7-42d6-a041-9b900744166f
&sktid=eb272a1e-e767-4041-9363-f8736579f898
&skt=2024-04-05T09%3A04%3A15Z
&ske=2024-04-06T09%3A19%3A15Z
&sks=b
&skv=2023-11-03
&sv=2023-11-03
&spr=https
&se=2024-04-06T09%3A19%3A24Z
&sr=c
&sp=rl
&sig=xxxxxx

对比Azure门户生成的有效SAS URI(账户密钥生成):

https://<account>.blob.core.windows.net/test
?sp=rl
&st=2024-04-05T08:52:05Z&se=2024-04-05T16:52:05Z
&spr=https
&sv=2022-11-02
&sr=c
&sig=xxxxxx

我遗漏了什么?

更新:问题可能与生成User Delegation密钥的RBAC权限不足有关,测试用的是账户密钥生成的。我会修复RBAC后验证,但疑惑为何权限不足却能生成URI而非抛出异常。


解答
  1. 核心问题:签名字符串中的容器不匹配
    从错误信息的AuthenticationErrorDetail可以看到,服务端用于验证的签名字符串中,目标容器是/blob/tmfootballdev/$root,但你实际要访问的是test容器。这说明生成SAS时,代码使用的容器信息与目标容器不一致,请检查传入的containerClient是否确实指向test容器,而非$root容器。

  2. User Delegation Key权限问题
    生成User Delegation SAS要求当前身份具备以下权限:

    • 至少拥有Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action权限
    • 或具备Storage Blob Data Contributor等内置角色

    如果权限不足,GetUserDelegationKeyAsync不会直接抛出异常,但返回的密钥是无效的,导致后续生成的SAS无法通过签名验证。

  3. 其他需要检查的点

    • 确认_accountName与containerClient.AccountName是同一个存储账户,避免因账户不一致导致签名错误
    • 检查本地时钟与Azure服务时钟是否同步,时间偏差可能导致SAS有效期验证失败
    • 验证BlobSasBuilder的参数:Resource = "c"是容器级SAS的正确取值,权限rl(List+Read)也符合需求
  4. 关于权限不足却能生成URI的疑问
    Azure存储服务在调用GetUserDelegationKeyAsync时,不会实时校验权限的有效性,仅会返回格式合法的密钥。只有在使用SAS发起请求时,服务端才会验证签名的合法性,因此会出现“能生成URI但无法使用”的情况。


内容的提问来源于stack exchange,提问作者Jakob Busk Sørensen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:54:52