CloudFront无法访问非静态托管S3 Bucket,PUT请求返回403
问题分析与解决步骤
核心问题定位
浏览器提示的「未签名的host头」是导致403的关键原因:通过CloudFront访问私有S3时,签名URL的签名范围未包含host请求头,而CloudFront转发请求时会携带该头,S3验证签名时发现未包含该头,直接拒绝请求。
具体解决措施
1. 生成签名URL时包含host头
在后端生成S3签名URL的逻辑中,必须将host头加入签名的签名头列表。以AWS Node.js SDK为例:
const params = { Bucket: '你的私有Bucket名称', Key: '目标文件的Key', Expires: 3600, Method: 'PUT', Headers: { 'host': '你的CloudFront域名' // 需与前端请求用的域名完全一致 } }; const signedUrl = s3.getSignedUrl('putObject', params);
2. 配置CloudFront转发host头
在CloudFront分发的对应S3源设置中,调整源请求策略:
- 创建自定义源请求策略,在「包含的请求头」中勾选
Host - 将该策略关联到目标S3源上,确保CloudFront转发请求时携带
host头到S3
3. 修正Bucket Policy权限
无需过度授权s3:*,精准配置即可:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity 你的OAI ID" }, "Action": [ "s3:PutObject" // 若需GET操作,可添加"s3:GetObject" ], "Resource": "arn:aws:s3:::你的私有Bucket名称/*" } ] }
4. 前端请求注意事项
Angular发起PUT请求时,直接使用CloudFront域名作为请求地址,不要手动修改host头,确保请求头中的host与签名时指定的域名完全一致。
内容的提问来源于stack exchange,提问作者user6680
相关产品推荐
相关产品推荐

