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

使用Node.js生成Azure存储SAS URL时遭遇认证失败问题

问题:生成Azure Blob存储SAS URL用于前端直接上传时签名不匹配错误

我尝试生成SAS URL返回给客户端,让客户端通过该URL直接PUT文件到Azure Blob存储,但一直遇到签名不匹配的认证错误。

我的后端端点代码(update 1):

router.get('/get-upload-url', async (req, res) => {
  const blobName = 'dummyBlobName.jpeg';

  const blobServiceClient = new BlobServiceClient(`https://${ACCOUNT_NAME}.blob.core.windows.net`, new StorageSharedKeyCredential(ACCOUNT_NAME, SAS_TOKEN));
  const containerClient = blobServiceClient.getContainerClient(CONTAINER_NAME);
  const blockBlobClient = containerClient.getBlockBlobClient(blobName);

  const startDate = new Date();
  const expiryDate = new Date(startDate);
  expiryDate.setMinutes(startDate.getMinutes() + 100);

  const sasToken = generateBlobSASQueryParameters({
    containerName: CONTAINER_NAME,
    blobName,
    permissions: BlobSASPermissions.parse('cw'),
    startsOn: startDate,
    expiresOn: expiryDate
  }, blobServiceClient.credential);

  const sasUrl = `${blockBlobClient.url}?${sasToken}`;

  res.json({ sasUrl });
});

app.use('/', router);

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

我用以下curl命令测试:

curl -X PUT -T ~/Downloads/dp.jpeg \
-H "x-ms-date: $(date -u)" \
-H "x-ms-blob-type: BlockBlob" \
"https://appstrolabstoragedev.blob.core.windows.net/imgx/dummyBlobName.jpeg?sv=2024-08-04&st=2024-07-29T12%3A52%3A55Z&se=2024-07-29T14%3A32%3A55Z&sr=b&sp=cw&sig=jsYb6VOm57avYu2eS2H26Q6vMkzSjdnjMI%2B80xygQ%2F8%3D"

得到的错误信息:

<?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:beee57d1-201e-005b-7db6-e1f5de000000
Time:2024-07-29T12:53:12.7097016Z</Message><AuthenticationErrorDetail>Signature did not match. String to sign used was cw
2024-07-29T12:52:55Z
2024-07-29T14:32:55Z
/blob/appstrolabstoragedev/imgx/dummyBlobName.jpeg
2024-08-04
b
</AuthenticationErrorDetail></Error>% 

我已经把blobName更新为'dummyBlobName.jpeg',但还是报错:

<?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:03849c77-001e-0087-46c0-e15f80000000 Time:2024-07-29T14:06:41.0301691Z</Message><AuthenticationErrorDetail>Signature did not match. String to sign used was cw 2024-07-29T14:05:50Z 2024-07-29T15:45:50Z /blob/appstrolabstoragedev/imgx/dummyBlobName.jpeg    2024-08-04 b       </AuthenticationErrorDetail></Error>%

解决方案

核心问题:你错误地将SAS_TOKEN传入了StorageSharedKeyCredential,这个类需要的是存储账户的访问密钥(而非SAS令牌)。生成SAS签名必须使用账户密钥,SAS令牌是客户端用于访问的最终凭证,不能用来生成新的SAS。

具体修复步骤

  • 替换凭证参数:把代码中的SAS_TOKEN替换为存储账户的访问密钥(可在Azure门户的「存储账户」→「访问密钥」页面获取)。
  • 日期处理优化:确保日期是UTC时间且去掉毫秒,避免签名时的细微时间差导致验证失败:
    const startDate = new Date(Date.now());
    startDate.setMilliseconds(0); // 移除毫秒部分
    const expiryDate = new Date(startDate);
    expiryDate.setMinutes(startDate.getMinutes() + 100);
    
  • 简化测试命令:使用SAS URL上传时,不需要添加x-ms-date请求头,Azure会通过SAS中的st(起始时间)和se(过期时间)验证请求有效性,去掉该头后重新测试:
    curl -X PUT -T ~/Downloads/dp.jpeg \
    -H "x-ms-blob-type: BlockBlob" \
    "你的SAS_URL"
    

修复后的核心代码

// 使用账户密钥而非SAS_TOKEN创建StorageSharedKeyCredential
const blobServiceClient = new BlobServiceClient(
  `https://${ACCOUNT_NAME}.blob.core.windows.net`,
  new StorageSharedKeyCredential(ACCOUNT_NAME, ACCOUNT_KEY) // 这里替换为ACCOUNT_KEY
);

额外建议

  • 不要硬编码账户密钥,使用环境变量管理(如process.env.AZURE_STORAGE_ACCOUNT_KEY),避免密钥泄露。
  • 合理设置SAS有效期,根据业务场景调整,避免过长有效期带来的安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 06:38:11