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

Azure Blob Storage SAS Token生成报错:签名字段格式异常(C#)

问题分析与修复方案

你遇到的「签名字段格式不正确」错误,核心原因是使用的存储服务版本(2022-11-02)要求签名串(String-to-Sign)包含更多字段,你的代码漏掉了几个必填的字段项(即使值为空也需要保留对应空行)。

具体问题点

Azure存储服务从版本2020-02-10开始,更新了服务SAS的签名串结构,必须包含以下字段(按顺序):

  1. 权限(signedPermissions)
  2. 开始时间(signedStart)
  3. 到期时间(signedExpiry)
  4. 规范资源(canonicalizedResource)
  5. 签名标识符(signedIdentifier,可选,空则留空行)
  6. IP范围(signedIp,可选,空则留空行)
  7. 协议(signedProtocol)
  8. 服务版本(signedVersion)
  9. 资源类型(signedResource,即sr参数的值)
  10. 快照时间(signedSnapshotTime,可选,空则留空行)
  11. 加密范围(signedEncryptionScope,可选,空则留空行)

你的代码中缺少了第9、10、11项,导致签名串格式不符合要求。

修正后的代码

private string GenerateSasToken(string accountName, string accountKey, string containerName, string blobName)
{
    // Define SAS parameters
    string signedPermissions = "r"; // Read permissions
    string signedStart = DateTime.UtcNow.AddMinutes(-5).ToString("yyyy-MM-ddTHH:mm:ssZ"); // Start time is 5 minutes ago to account for clock skew
    string signedExpiry = DateTime.UtcNow.AddHours(8).ToString("yyyy-MM-ddTHH:mm:ssZ"); // Expiry time 8 hours from now
    string signedResource = "b"; // Blob resource type
    string signedVersion = "2022-11-02"; // Storage service version
    string signedProtocol = "https"; // HTTPS only
    string signedIp = ""; // No IP restriction

    // Canonicalized resource: "/blob/account/container/blob"
    string canonicalizedResource = $"/blob/{accountName}/{containerName}/{blobName}";

    // 修正后的签名串构造,补充缺失的字段项
    string stringToSign = $"{signedPermissions}\n" +
                          $"{signedStart}\n" +
                          $"{signedExpiry}\n" +
                          $"{canonicalizedResource}\n" +
                          $"\n" + // signedIdentifier (optional, left empty)
                          $"{signedIp}\n" +
                          $"{signedProtocol}\n" +
                          $"{signedVersion}\n" +
                          $"{signedResource}\n" + // 新增:资源类型字段
                          $"\n" + // signedSnapshotTime (empty, leave blank line)
                          $"\n"; // signedEncryptionScope (empty, leave blank line)

    // Decode the account key from Base64
    byte[] keyBytes = Convert.FromBase64String(accountKey);

    // Create HMAC-SHA256 hash
    using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
    {
        byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
        string signature = Convert.ToBase64String(signatureBytes);

        // Construct the SAS token
        var sasToken = HttpUtility.ParseQueryString(string.Empty);
        sasToken["sp"] = signedPermissions;
        sasToken["st"] = signedStart;
        sasToken["se"] = signedExpiry;
        sasToken["spr"] = signedProtocol;
        sasToken["sv"] = signedVersion;
        sasToken["sr"] = signedResource;
        sasToken["sig"] = HttpUtility.UrlEncode(signature); // URL-encoded signature

        // Return the full blob URL with the SAS token
        return $"https://{accountName}.blob.core.windows.net/{containerName}/{blobName}?{sasToken}";
    }
}

额外注意事项

  • 确保accountKey是正确的Base64编码密钥,没有多余的空格或换行符;
  • 日期格式yyyy-MM-ddTHH:mm:ssZ符合Azure要求的ISO 8601 UTC标准,不要使用本地时间;
  • 签名串中的每个字段必须严格按顺序排列,空字段对应的空行不能省略。

内容的提问来源于stack exchange,提问作者Mohammad Elbaba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:17:12