Azure Blob Storage SAS Token生成报错:签名字段格式异常(C#)
问题分析与修复方案
你遇到的「签名字段格式不正确」错误,核心原因是使用的存储服务版本(2022-11-02)要求签名串(String-to-Sign)包含更多字段,你的代码漏掉了几个必填的字段项(即使值为空也需要保留对应空行)。
具体问题点
Azure存储服务从版本2020-02-10开始,更新了服务SAS的签名串结构,必须包含以下字段(按顺序):
- 权限(signedPermissions)
- 开始时间(signedStart)
- 到期时间(signedExpiry)
- 规范资源(canonicalizedResource)
- 签名标识符(signedIdentifier,可选,空则留空行)
- IP范围(signedIp,可选,空则留空行)
- 协议(signedProtocol)
- 服务版本(signedVersion)
- 资源类型(signedResource,即
sr参数的值) - 快照时间(signedSnapshotTime,可选,空则留空行)
- 加密范围(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
相关产品推荐
相关产品推荐

