Azure Function访问Blob Storage私有托管站点认证失败问题
核心错误原因
你请求Blob Storage时携带的Bearer令牌不符合服务鉴权要求:
从请求头x-ms-token-aad-access-token获取的令牌,是AAD颁发给你的Azure Function应用的用户登录令牌,该令牌的受众(aud声明)为你的Function关联的App Registration标识,并非Blob Storage服务认可的资源受众,因此存储服务会直接返回签名/鉴权失败错误。
修复步骤
1. 调整令牌获取逻辑,使用OBO流换取存储服务的有效令牌
不能直接透传用户访问Function的令牌去请求Blob,需要通过代表用户(On-Behalf-Of, OBO) 流,用当前用户的登录令牌,向AAD申请颁发给Blob Storage服务的访问令牌:
- 到你关联的App Registration配置页,添加API权限:选择
Azure Storage服务下的user_impersonation委托权限,完成租户管理员同意配置。 - 为App Registration生成客户端密钥(或配置证书认证),用于OBO流的服务端认证。
- 替换原有直接读取请求头令牌的逻辑,参考如下代码换取存储服务令牌:
// 需提前在Function项目中引入Microsoft.Identity.Client包 // 获取用户访问Function时携带的原始令牌 var userToken = req.Headers .FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-access-token", StringComparison.OrdinalIgnoreCase)) .Value.FirstOrDefault(); // 构建机密客户端用于OBO流请求 var cca = ConfidentialClientApplicationBuilder .Create("你的App Registration客户端ID") .WithClientSecret("你生成的App Registration客户端密钥") .WithTenantId("你的AAD租户ID") .Build(); // 换取受众为Blob Storage的访问令牌 var tokenResult = await cca.AcquireTokenOnBehalfOf( scopes: new[] { "https://storage.azure.com/user_impersonation" }, userAssertion: new UserAssertion(userToken) ).ExecuteAsync(); // 后续请求Blob时使用tokenResult.AccessToken作为Bearer令牌即可 var validBlobToken = tokenResult.AccessToken;
- 你原有代码中的
RefreshToken逻辑也需要同步调整:令牌过期时重新走OBO流换取新的存储令牌,不要直接刷新原有的Function访问令牌。
2. 修正存储账号的权限配置
- 移除你之前在存储允许令牌受众中配置的App ID,该配置不适用于当前场景。
- 为需要访问HTML文件的用户/用户组分配存储账号的对应角色:仅需读取权限的话,分配存储Blob数据读者角色即可,作用域选择你存放HTML文件的容器或整个存储账号。
3. 可选优化
- 建议使用官方Blob存储SDK替代原生HttpClient发起请求,不需要手动维护
x-ms-version头、处理请求重试和内容解析,减少兼容问题。 - 你当前代码中使用的
2017-11-09存储服务版本过旧,即使继续用HttpClient请求,也建议升级到2020年后的稳定服务版本。
内容的提问来源于stack exchange,提问作者Morgan Soren
相关产品推荐
相关产品推荐

