我通过将我的 S3 存储桶切换为用作 CloudFront 自定义源(即无源访问身份)的静态网站,解决了(并且......最终放弃了我的解决方案)这个问题。我使用了aws:Referer 存储桶策略来限制仅访问来自 CloudFront 的请求。
注意 Referer 标头通常包含请求的 URL。在这种情况下,您只是用您在 CloudFront 和 S3 之间共享的唯一秘密令牌覆盖它。
这在“使用网站端点作为来源,访问受Referer标头限制”下描述为on this AWS Knowledge center page。
我最终使用了一个随机 UUID 作为我的令牌,并在我的 CloudFront Origin 配置中设置了它。
使用相同的 UUID,我最终得到了一个像这样的存储桶策略:
{
"Id": "Policy1603604021476",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1603604014855",
"Principal": "*",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::example/*",
"Condition": {
"StringEquals": {
"aws:Referer": "b4355bde-9c68-4410-83cf-058540d83491"
}
}
},
{
"Sid": "Stmt1603604014855",
"Principal": "*",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::example",
"Condition": {
"StringEquals": {
"aws:Referer": "b4355bde-9c68-4410-83cf-058540d83491"
}
}
}
]
}
需要s3:ListBucket 策略才能使 404 正常工作。如果没有,您将获得标准的 S3 AccessDenied 错误页面。
现在,我的每个 S3 来源都可以有不同的错误页面行为,这些行为是在 S3 方面(而不是在 CloudFront 中)配置的。
跟进我不推荐这种方法,原因如下:
- 不可能让 S3 在 HTTPS 上托管您的静态网站,因此您的 Referer 令牌将被明文发送。当然,这可能会在 AWS 网络上,但这仍然不是我所希望的。
- 无论如何,每个 S3 存储桶只会得到一个错误文档,因此与 CloudFront 行为相比,这并没有太大的改进。