S3 的私有内容 CORS 问题

Posted

技术标签:

【中文标题】S3 的私有内容 CORS 问题【英文标题】:Private Content CORS issues with S3 【发布时间】:2019-05-20 04:48:18 【问题描述】:

问题

很长一段时间以来,我一直在摸不着头脑,试图浏览围绕 AWS 生态系统的许多 3 字母首字母缩写词服务。

我要做的是在网站上显示内容(pdf、图像、视频),其中该内容只能在网站上显示给经过身份验证的用户,不能可下载或公开访问

我的问题是,无论我尝试什么,在从前端请求图像内容时都会出现 403 错误,除非允许对存储桶进行完全公开访问。

应用程序的架构是一个前端 JS 应用程序,通过托管在 S3 上的 CloudFront 分发提供服务。这与托管在 EC2 上的后端进行通信。

到目前为止我已经尝试过什么

CORS 配置

关于该主题的documentation 似乎暗示只是创建 CORS 规则以允许从我的网站访问存储桶中的对象。

我为存储桶创建了一个类似于以下内容的 CORS 策略,它应该允许访问存储桶中的对象:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>http://*.websitename.com</AllowedOrigin>
    <AllowedOrigin>https://*.websitename.com</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

这里不走运,403 错误。为了测试它是否可能不是 CORS 配置,我打开了 CORS 策略以尝试允许公共 CORS 访问存储桶,如下所示:

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

这里也没有运气,*** 上的其他人提到 AllowedOrigin: * 存在一点记录问题,并尝试以下操作:

<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>http://*</AllowedOrigin>
    <AllowedOrigin>https://*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

一位用户在 *** 上指出,直接链接的内容默认不发送 Origin 标头,这意味着 S3 会将其解释为内部请求并发送 403 禁止错误。解决方法是在图片标签中添加crossorigin="anonymous"

将此属性添加到img 标签后,确认标头发送正确。它在请求标头中发送正确的Origin: mywebsitename.com,我什至收到了正确的response 标头,包括我的网站在内的允许来源。

Cloudfront 分发问题

根据this 的回答,Cloudfront 默认情况下不会将标头转发到 S3。我已经采取了转发所有标头的步骤,包括Access-Control-Allow-MethodsAccess-Control-Allow-Origin

此外,另一个人建议 cloudfront 偶尔会出现奇怪的缓存问题。我还向图像添加了一个随机查询字符串,结果相同。

两者之后,仍然是 403。

我对整个设置有点摸不着头脑,正在考虑其他选项,例如后端的代理服务器,我自己处理授权。虽然允许所有起源不是我的最终目标,但它应该在这一点上起作用。有人有什么想法吗?

【问题讨论】:

只是一个问题:您是否从 Cloudfront 添加了对存储桶的访问权限?如此处所述:aws.amazon.com/de/premiumsupport/knowledge-center/… 【参考方案1】:

我找到了可提供我需要的解决方案的存储桶策略。

例如:


"Version": "2012-10-17",
"Id": "http referer policy example",
"Statement": [
    
        "Sid": "Allow get requests originating from www.example.com and example.com.",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::url/*",
        "Condition": 
            "StringLike": 
                "aws:Referer": [
                    "https://example.com/*",
                    "https://www.example.com/*"
                ]
            
        
    
]

【讨论】:

【参考方案2】:

content can only be displayed on the website to authenticated users and not be downloaded or publicly accessible

您的 CF 或 S3 将所有内容视为未经身份验证。将您的 S3 配置为允许来自 CF 的所有请求,并尝试使用 Lambda@Edge 检查身份验证并允许或拒绝请求。另一种选择是对 S3 使用签名 URL,但这涉及更多工作。

【讨论】:

以上是关于S3 的私有内容 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

被 CORS 数据和 S3 污染的画布

ViewerJS、S3 和 CORS - 从不同的 S3 存储桶/域加载资源

没有 S3 存储桶的 AWS Cloudfront CORS 标头

用于访问无法从自定义域访问的 S3 私有内容的签名 URL

如何使用 html2Canvas 和 AWS S3 图像处理 CORS?

从浏览器缓存提供图像时,AWS S3 + CloudFront 会出现 CORS 错误