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

Azure中Put Block List操作返回403 Forbidden错误求助

分析你的Azure Put Block List 403 Forbidden错误

嘿,我来帮你拆解这个问题——从你提供的错误响应里的AuthenticationErrorDetail,就能直接找到签名验证失败的根源:你构造的签名字符串和Azure服务器实际用来校验的字符串不一致,主要有两个核心问题:


1. 签名字符串漏掉了Content-Type字段

先看服务器给出的对比信息:

服务器使用的签名字符串:PUT 110 text/plain x-ms-date:Wed, 16 May 2018 06:22:34 GMT x-ms-version:2017-07-29 /storagekaren/dbstore/ddd.txt comp:blocklist
你构造的签名字符串:

PUT


110







x-ms-date:Tue, 15 May 2018 10:54:08 GMT
x-ms-version:2017-07-29
/storagekaren/dbstore/ddd.txt
comp:blocklist

Azure的SharedKey签名规则明确要求:如果你的请求里带有Content-Type头,必须把它包含到规范化的签名字符串里。你的请求因为发送了XML格式的请求体,HttpClient自动给你加了Content-Type: text/plain(或者你手动设置了但没注意),但你在生成签名时完全漏掉了这个字段,这直接导致签名不匹配。


2. 签名用的日期和实际请求的日期对不上

你生成签名时用的x-ms-date是Tue, 15 May 2018 10:54:08 GMT,但实际发送请求时的日期是Wed, 16 May 2018 06:22:34 GMT(从错误详情里能看到)。

Azure对签名的时间一致性要求很严格:签名里的日期必须和请求头里的x-ms-date完全一致,差一分钟都不行。这种情况通常是因为你提前生成了签名,但隔了很久才发请求,或者代码里生成日期和设置请求头的逻辑没同步导致的。


具体修复步骤

第一步:修正签名字符串的构造

按照Azure的规范,你需要把Content-Type加进去,并且保证格式正确。针对你的Put Block List请求,正确的规范化字符串应该是这样的(如果你的请求体是XML,建议显式用application/xml代替自动生成的text/plain):

PUT\n
\n
\n
110\n
\n
application/xml\n
\n
\n
\n
\n
\n
x-ms-date:Wed, 16 May 2018 06:22:34 GMT\n
x-ms-version:2017-07-29\n
/storagekaren/dbstore/ddd.txt\n
comp:blocklist

注意:每个字段之间的换行必须是单个\n,不能有多余的空行或空格,顺序也不能乱。

第二步:让签名日期和请求头日期保持同步

生成签名和设置请求头时,要用同一个日期值,避免时间差。比如在代码里可以这么写:

var currentUtcDate = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);

// 用这个日期构造规范化字符串
var canonicalizedString = $"PUT\n\n\n110\n\napplication/xml\n\n\n\n\n\nx-ms-date:{currentUtcDate}\nx-ms-version:2017-07-29\n/storagekaren/dbstore/ddd.txt\ncomp:blocklist";

// 生成授权头
var authHeader = CreateAuthorizationHeader(canonicalizedString);

// 设置请求头时直接用同一个日期
client.DefaultRequestHeaders.Remove("x-ms-date");
client.DefaultRequestHeaders.Add("x-ms-date", currentUtcDate);
client.DefaultRequestHeaders.Add("Authorization", authHeader);

第三步:显式设置请求的Content-Type

发送请求时,手动指定Content-Type为application/xml,确保和签名里的字段一致:

var xmlBody = @"<?xml version=""1.0"" encoding=""utf-8""?>
<BlockList>
  <Uncommitted>MDAwMDAwMDAwMA==</Uncommitted>
</BlockList>";
var requestContent = new StringContent(xmlBody, Encoding.UTF8, "application/xml");
var response = await client.PutAsync("https://storagekaren.blob.core.windows.net/dbstore/ddd.txt?comp=blocklist", requestContent);

额外检查点

  • 生成签名后,可以把你的规范化字符串和错误里服务器给出的字符串逐字符对比,确保顺序、大小写、空格、换行完全一致。
  • 再核对一遍存储账户密钥,别不小心复制错了(比如末尾的等号有没有漏掉)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:03:36