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

Azure Blob SAS令牌生成遇Signature did not match错误求助

Azure Blob SAS令牌生成签名不匹配问题排查

问题背景

需用JavaScript生成Azure Blob的SAS令牌,编写的代码生成URL后在浏览器访问时触发AuthenticationFailed错误,提示Signature did not match。代码将用于ServiceNow业务规则,需排查修复。

原代码

var CryptoJS = require("crypto-js/core")

var blobAccount = 'ACCOUNTNAME';
var blobContainer = 'CONTAINERNAME/PATH_TO_FILE';
var sasToken = '';
var storageAccountKey = 'KEY2';

// 计算过期时间
var currentDate = new Date();
var expiration = new Date(currentDate.getTime() + (100 * 365 * 24 * 60 * 60 * 1000));

var st = currentDate.toISOString().slice(0,19)+'Z';
var se = expiration.toISOString().slice(0,19)+'Z';
var sv = '2018-11-09';
var sp = 'r';
var sr = 'b';

var canonicalizedResource = "/"+blobAccount+"/"+blobContainer;
var stringToSign = sp+'\n'+st+'\n'+se+'\n'+canonicalizedResource+'\n'+sv+'\n'+sr+'\n'+'\n'+'\n'+'\n'+'\n'+'\n'+'\n'+'\n';
var signature = CryptoJS.HmacSHA256(stringToSign, CryptoJS.enc.Base64.parse(storageAccountKey)).toString(CryptoJS.enc.Base64);
sasToken = encodeURIComponent(signature)+"&st="+st.replaceAll(':','%3A')+"&se="+se.replaceAll(':','%3A')+"&sv=2018-11-09&sp=r&sr=b"

var url = "https://"+blobAccount+".blob.core.windows.net/"+blobContainer+"?"+"sig="+sasToken

console.log(sasToken);
console.log(url)

错误信息

<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:1145b24b-201e-005c-3b3b-86f4f3000000 Time:2023-05-14T08:10:23.2762870Z</Message>
<AuthenticationErrorDetail>Signature did not match. String to sign used was r 2023-05-14T08:09:57Z 2123-04-20T08:09:57Z /blob/ACCOUNTNAME/CONTAINERNAME/PATH_TO_FILE 2018-11-09 b </AuthenticationErrorDetail>
</Error>

问题分析与修复

从错误信息中的String to sign used was可以看出,Azure服务器实际使用的签名字符串和代码中生成的存在核心差异:

1. 核心错误:CanonicalizedResource格式错误

Azure服务器期望的资源路径是/blob/ACCOUNTNAME/CONTAINERNAME/PATH_TO_FILE,但原代码构造的是/ACCOUNTNAME/CONTAINERNAME/PATH_TO_FILE,缺少/blob前缀。针对Blob服务的SAS签名,CanonicalizedResource必须以/blob/<存储账户名>/<资源路径>开头。

2. StringToSign格式不规范

针对API版本2018-11-09,StringToSign的字段顺序和空行必须严格遵循规则,未使用的字段需留空行,不能随意添加或省略。

3. CryptoJS模块不完整

原代码仅导入crypto-js/core,缺少HmacSHA256和Base64编码的模块支持,可能导致签名计算错误。

4. URL编码方式不可靠

手动替换:为%3A不如使用encodeURIComponent通用可靠。

修复后的代码

// 导入完整CryptoJS模块,确保包含HmacSHA256和Base64功能
var CryptoJS = require("crypto-js");

var blobAccount = 'ACCOUNTNAME';
var blobContainer = 'CONTAINERNAME/PATH_TO_FILE';
var sasToken = '';
var storageAccountKey = 'KEY2';

// 计算过期时间
var currentDate = new Date();
var expiration = new Date(currentDate.getTime() + (100 * 365 * 24 * 60 * 60 * 1000));

var st = currentDate.toISOString().slice(0,19)+'Z';
var se = expiration.toISOString().slice(0,19)+'Z';
var sv = '2018-11-09';
var sp = 'r';
var sr = 'b';

// 修正CanonicalizedResource格式,添加/blob前缀
var canonicalizedResource = `/blob/${blobAccount}/${blobContainer}`;

// 严格按照2018-11-09版本的StringToSign格式构造,未使用字段留空行
var stringToSign = [
    sp,
    st,
    se,
    canonicalizedResource,
    "", // Identifier(留空)
    "", // IPAddress(留空)
    "", // Protocol(留空)
    sv,
    sr,
    "", // SnapshotTime(留空)
    "", // EncryptionScope(留空)
    "", // CacheControl(留空)
    "", // ContentDisposition(留空)
    "", // ContentEncoding(留空)
    "", // ContentLanguage(留空)
    ""  // ContentType(留空)
].join('\n');

// 生成签名
var signature = CryptoJS.HmacSHA256(stringToSign, CryptoJS.enc.Base64.parse(storageAccountKey)).toString(CryptoJS.enc.Base64);

// 拼接SAS令牌,使用encodeURIComponent统一编码特殊字符
sasToken = `sig=${encodeURIComponent(signature)}&st=${encodeURIComponent(st)}&se=${encodeURIComponent(se)}&sv=${sv}&sp=${sp}&sr=${sr}`;

// 构造完整访问URL
var url = `https://${blobAccount}.blob.core.windows.net/${blobContainer}?${sasToken}`;

console.log(sasToken);
console.log(url);

关键注意事项

  • CanonicalizedResource必须准确:不同Azure服务(Blob/File/Queue)的CanonicalizedResource前缀不同,Blob服务必须加/blob。
  • StringToSign格式严格匹配API版本:每个API版本的签名字符串格式可能有差异,需严格遵循对应版本的规则。
  • 确保CryptoJS模块完整:若使用模块化导入,需单独引入crypto-js/hmac-sha256和crypto-js/enc-base64。
  • 参数编码要彻底:所有含特殊字符的参数(如st、se)都需用encodeURIComponent编码,避免URL解析错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:52:37