如何限制AWS S3存储桶读写访问仅允许来自自有静态网站的请求
核心问题定位
你现在的配置漏了两个关键校验点,才会出现外部可直接通过URL访问的问题:
- 原策略只匹配
http://example.com/*的Referer,漏了当前站点常用的https协议Referer,同时没有显式拦截无Referer的请求——用户直接输入S3 URL访问时,请求头不会携带Referer,这类请求只要有其他关联权限(比如之前的ACL设了公共读)就会被放行,绕过你的限制。 - 你之前开启Block Public Access的ACL选项后上传报403,本质是之前的上传逻辑依赖给单个对象附带公共读ACL权限,当ACL层面的公共访问被拦截时,对应的上传请求自然被拒绝。
可落地的分步配置
1. 替换成正确的Bucket Policy
把原有的策略替换为下面的配置,注意把存储桶ARN替换成你自己的实际值:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowWebRelatedAccess", "Effect": "Allow", "Principal": "*", "Action": [ "s3:PutObject", "s3:GetObject" ], "Resource": "arn:aws:s3:::你的存储桶名称/*", "Condition": { "StringLike": { "aws:Referer": [ "http://example.com/*", "https://example.com/*" ] } } }, { "Sid": "BlockDirectNoRefererAccess", "Effect": "Deny", "Principal": "*", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::你的存储桶名称/*", "Condition": { "StringLike": { "aws:Referer": "" } } } ] }
这里的Deny规则优先级最高,只要请求没有匹配到允许的Referer(包括直接在浏览器输URL、命令行curl直连这类场景),哪怕有其他权限也会被强制拦截。
2. 正确开启Block Public Access,避免上传403
把存储桶的「Block public access」4个选项全部勾选开启,这里不会再触发你之前遇到的上传403问题,前提是调整上传逻辑:
- 上传文件时不要再给请求附带
x-amz-acl: public-read这类对象ACL参数,所有读写权限完全由上面的Bucket Policy控制。因为现在的策略已经明确允许带你站点Referer的PutObject请求,S3会正常接收文件存储,不会触发公共ACL的拦截规则。
3. 效果校验
- 正常访问:你网站页面加载图片、用户通过网站上传文件时,浏览器会自动携带对应域名的Referer头,请求会被Allow规则放行,功能正常。
- 拦截场景:用户直接在浏览器地址栏输入S3对象URL访问时,请求不会携带Referer头,会被Deny规则拦截返回403,符合访问限制要求。
额外注意事项
- 移除原策略里不必要的
s3:GetObjectAcl权限,这类权限属于过度授权,没有实际使用需求。 - 如果你的站点有二级域名(比如
admin.example.com、static.example.com),记得把对应域名的Referer规则补充到Allow条件的列表里,避免漏匹配。 - 如果后续需要更高的安全级别(避免Referer被恶意伪造的场景),可以替换为预签名URL的鉴权方案,当前配置已经可以覆盖静态站的日常使用需求。
内容的提问来源于stack exchange,提问作者Camil
相关产品推荐
相关产品推荐

