s3存储桶策略仅依赖referer检查无法真正防盗链,因其字段易伪造且存在空referer误拦问题;可靠方案必须采用s3私有化+cloudfront+aws waf web acl三层组合校验。

直接说结论:S3 存储桶策略本身不能实现真正的“防盗链”,它只能做 Referer 检查,而这个字段极易伪造;真正可靠的防盗链必须依赖 CloudFront + WAF(Web ACL)组合,且 S3 必须设为私有、禁用公有访问。
为什么只靠 S3 存储桶策略做 Referer 检查不靠谱
S3 存储桶策略支持 aws:Referer 条件键,看起来能限制来源域名:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"StringNotLike": {
"aws:Referer": ["https://my-site.com/*", "https://www.my-site.com/*"]
}
}
}
]
}
但问题在于:
-
Referer是 HTTP 请求头,客户端可任意构造(curl -H "Referer: https://evil.com" ...) - 浏览器隐私模式、某些 PWA 场景、甚至部分移动端 WebView 可能不发送
Referer,导致合法请求被误拒 - 策略一旦生效,所有未匹配的请求(包括你自己的 CLI、CI/CD 下载、预签名 URL 调试)都会返回
403 Forbidden - 策略不区分 GET/HEAD,也无法校验时间戳或签名,对自动化爬虫毫无约束力
正确路径:S3 私有化 + CloudFront + WAF Web ACL
这是当前 AWS 官方推荐且生产环境验证过的链路。关键点是:S3 不暴露公网地址,所有流量必须经 CloudFront 分发,再由 WAF 做真实校验。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 关闭 S3 存储桶的「阻止公有访问」开关 → 必须取消勾选,否则 CloudFront 无法以 OAI 身份读取
- 创建 CloudFront 分发时,源类型选「S3 bucket」,并勾选「Use an origin access identity (OAI)」→ 这会让 CloudFront 自动修改 S3 策略,只允许该 OAI ARN 访问
- 在 CloudFront 行为(Behavior)中启用「Cache Based on Selected Request Headers」→ 至少勾选
Referer和User-Agent(便于后续 WAF 规则细化) - WAF Web ACL 绑定到 CloudFront 后,添加规则:
• 匹配Referer字段是否来自白名单域名(仍需配合其它条件)
• 更可靠的是加一条「自定义规则」:检查请求是否携带有效 JWT 或时间戳签名(需后端签发)
• 强制要求User-Agent非空且非常见爬虫标识(如python-requests、curl)
Composer 私有站场景下的特殊处理
Composer 的 composer install 或 composer update 默认通过 HTTP GET 下载 dist 包(zip/tar),不带 Referer,也不走浏览器,所以纯 aws:Referer 策略会直接拦死。
- 必须为 Composer 客户端生成专用预签名 URL(
getSignedUrl),有效期建议 5–15 分钟,URL 中嵌入X-Amz-Signature和X-Amz-Expires - CloudFront 行为中要配置「Cache Policy」:将
Authorization、X-Amz-Signature、X-Amz-Expires等签名参数加入缓存键(Cache Key) - 若使用 Packagist 兼容协议(如
packages.json动态生成),后端需在返回的dist.url字段中注入带签名的 CloudFront URL,而非原始 S3 链接 - 禁止在
composer.json中硬编码 S3 公网 endpoint(如https://my-bucket.s3.us-east-1.amazonaws.com/...),这等于绕过所有防护
容易被忽略的权限细节
很多人卡在「明明 WAF 放行了,还是 403」,往往败在权限链断裂:
- OAI 的 IAM 角色必须拥有
s3:GetObject权限,且资源 ARN 写成"arn:aws:s3:::my-bucket/*"(结尾的/*不能漏) - CloudFront 默认不转发
Authorization头,如果用了签名 URL,需在行为中设置「Whitelist Headers」包含Authorization、X-Amz-*系列头 - WAF 规则动作选
Block时,响应是 403;选Count时不会拦截,容易误判规则生效 - S3 存储桶策略里如果残留旧的
Allow公开语句,会与 OAI 策略冲突,务必清空或显式Deny非 OAI 请求
真正起作用的从来不是单点策略,而是 S3 → CloudFront → WAF 这三层权限叠加后的最小交集。任何一层松动,防盗链就形同虚设。










