Angular从Azure Blob获取图片时遇403认证错误,如何解决?
修复Azure Blob存储图片获取403认证错误
出现403 Server failed to authenticate the request错误,核心原因是请求未通过Azure Blob的身份验证,以下是针对性的修复方案:
1. 确认Blob容器的访问权限配置
- 如果打算用匿名访问:登录Azure门户,找到目标存储账户的Blob容器,将访问级别设置为「Blob」或「Container」(而非默认的「Private」)。只有设置为公共访问级别,才能无需认证直接获取Blob内容。
- 如果是私有容器:必须在请求中携带有效的认证凭证,不能直接用裸URL访问。
2. 验证请求URL的有效性
- 若使用SAS令牌访问私有容器:检查
environment.receiptLogoUrl是否包含完整且有效的SAS参数。SAS令牌需满足:- 包含读权限(
sp=r) - 有效期(
st和se)覆盖当前时间 - 签名(
sig)未过期且生成时使用了正确的存储账户密钥 - URL格式正确:Blob地址后以
?拼接SAS参数(例如https://xxx.blob.core.windows.net/container/blob.png?sp=r&st=...&se=...&sig=...)
- 包含读权限(
- 排查URL拼写错误:确认容器名、Blob文件名、存储账户后缀(
.blob.core.windows.net)无拼写错误。
3. 在请求中添加认证信息(私有容器场景)
方式一:使用SAS令牌(推荐前端场景)
确保environment.receiptLogoUrl已附带有效的SAS令牌,无需额外修改请求头,直接使用现有代码即可(前提是SAS参数正确)。
方式二:使用Azure AD令牌
如果通过Azure AD身份验证,需在请求中添加Authorization头:
import { HttpHeaders } from '@angular/common/http'; public getBase64Image(): Observable<string> { // 假设已通过Azure AD SDK获取到访问令牌 const accessToken = 'your-azure-ad-access-token'; const headers = new HttpHeaders().set('Authorization', `Bearer ${accessToken}`); return this.http.get(environment.receiptLogoUrl, { responseType: 'blob', headers: headers }) .pipe( switchMap((blob: Blob) => { return new Observable<string>((observer) => { const reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = () => { observer.next(reader.result as string); observer.complete(); }; reader.onerror = (err) => observer.error(err); }); }) ); }
4. 检查存储账户的CORS配置
前端跨域请求Blob资源时,需确保存储账户的CORS规则允许你的前端域名:
- 登录Azure门户,进入目标存储账户 → 「资源共享 (CORS)」
- 添加或修改规则:
- 允许的源(Allowed Origins):填写你的前端域名(例如
https://your-frontend-domain.com,或用*临时测试) - 允许的方法(Allowed Methods):勾选
GET - 允许的头(Allowed Headers):填写
*或必要的请求头 - 公开的头(Exposed Headers):按需配置
- 最大年龄(Max Age):设置合理值(例如
86400)
- 允许的源(Allowed Origins):填写你的前端域名(例如
5. 验证存储账户密钥的有效性
如果是用存储账户密钥生成的SAS令牌,检查:
- 密钥是否为当前有效的存储账户密钥(避免密钥被轮换后使用旧密钥生成SAS)
- 生成SAS时是否选择了正确的服务(Blob)和资源类型(Object)
代码优化(非错误修复,但可简化逻辑)
原代码中readAsBinaryString结合btoa的方式可以用readAsDataURL直接替换,减少手动编码步骤:
public getBase64Image(): Observable<string> { return this.http.get(environment.receiptLogoUrl, { responseType: 'blob' }) .pipe( switchMap((blob: Blob) => { return new Observable<string>((observer) => { const reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = () => { observer.next(reader.result as string); observer.complete(); }; reader.onerror = (error) => observer.error(error); }); }) ); }
内容的提问来源于stack exchange,提问作者Dilshan Prasad
相关产品推荐
相关产品推荐

