由于 CORS,无法从 S3 存储桶中获取图像

Posted

技术标签:

【中文标题】由于 CORS,无法从 S3 存储桶中获取图像【英文标题】:Fetching an image from S3 bucket is not working because of CORS 【发布时间】:2019-11-29 20:47:36 【问题描述】:

问题是当我尝试使用fetch API 获取时,我收到了 cors 错误(响应标头不包含 Access-Control-Allow-Origin)。这是我在 S3 中的 cors 配置 -

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

代码可以在这里找到 - https://codepen.io/sourov0805045/pen/OKVBXM?editors=1111

我检查了响应标头,发现它不包含 Allow-Access-Control-Origin 标头。

但是如果我将它添加到 &lt;img&gt; 标记中,这会正常工作,这非常令人费解。那时响应标头中也没有Access-Control-Allow-Origin,但图像加载正常。

A 已尝试与axios 相同,但没有效果。

请告诉我您对如何解决此问题的建议。

【问题讨论】:

如果您在同源上下文中请求对象,然后在跨源上下文中请求对象,则 S3 上的 CORS 会损坏,因为 S3 不会在非 CORS 响应上添加 Vary: Origin 响应标头。我在serverfault.com/a/856948/153161 解决了这个缺陷,其中包括对 CloudFront 的引用,但无论是否使用 CloudFront,S3 都是问题的根源。 嗨@Michael-sqlbot 我认为我的问题更基本。如果你看到 codepen,你会看到我只是发出一个 fetch 请求,所以它并没有真正使用缓存。此外,该问题在 Firefox 中也可以重现。 你已经解决了吗?我现在在您的 codepen 编辑器中单击按钮时得到正确的响应标头:Accept-Ranges: bytes Access-Control-Allow-Methods: GET, POST, PUT, HEAD, DELETE Access-Control-Allow-Origin: * Content -长度:1573767 内容类型:应用程序/八位字节流日期:格林威治标准时间 2019 年 7 月 24 日星期三 19:41:17 ETag:“8e26c03714ab4d8e185c29b1c04639f0” 最后修改时间:2019 年 6 月 26 日星期三 19:18:40 GMT 服务器:AmazonS3 变化:来源,访问控制请求标头,访问控制请求方法 x-amz-id-2:[...] x-amz-request-id:[...] 是的,已经解决了,稍后会更新问题。 @RasheduzzamanSourov 你有没有机会提供你承诺的更新:D? 【参考方案1】:

首先删除不必要的变量:从命令行使用 cURL。

第 1 步:发出飞行前OPTIONS 请求:

curl -H "Origin: http://example.com" \
      -H "Access-Control-Request-Method: GET" \
      -H "Access-Control-Request-Headers: X-Requested-With" \
      -X OPTIONS --verbose \
      'https://twisker-s3-files.s3.us-east-2.amazonaws.com/files/-GxfyX_dZ-6313383.jpg'

您在输出中寻找的响应标头是:

...
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, PUT, HEAD, DELETE
< Access-Control-Allow-Headers: x-requested-with
< Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
...

第 2 步:发出 GET 请求:

~ $ curl --head 'https://twisker-s3-files.s3.us-east-2.amazonaws.com/files/-GxfyX_dZ-6313383.jpg' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/75.0.3770.142 Safari/537.36' -H 'Referer: https://cdpn.io/boomboom/v2/index.html?editors=1111&key=iFrameKey-a88ea9ee-51a6-0ae2-7350-951a5b1e4e56' -H 'Origin: https://cdpn.io' --compressed

回复如下:

HTTP/1.1 200 OK
x-amz-id-2: 9D3J5BnHo7YocXQicso+eQAC/PlyoOMpc5QXd+G77HMtWTOd8kYymcJnQ0T8J7tqXetMZgVO8Rw=
x-amz-request-id: 6CE1579D5B039163
Date: Thu, 25 Jul 2019 02:18:41 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, HEAD, DELETE
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Wed, 26 Jun 2019 19:18:40 GMT
ETag: "8e26c03714ab4d8e185c29b1c04639f0"
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 1573767
Server: AmazonS3

注意事项:

    Access-Control-Allow-OriginAccess-Control-Allow-Methods 存在 它们的值看起来是正确的,所以 CORS 应该对你有用(它在你的 URL 上对我有用)

https://www.test-cors.org 可用于测试 CORS 请求。它在请求的每个阶段都给出了一些输出。

最后,浏览器在缓存 pre-flight OPTIONS 请求方面非常积极。因此,如果您正在查看 chrome 网络调试工具,您可能看不到 pre-flight OPTIONS 请求。有时重新启动 chrome 会清除 OPTIONS 缓存,有时需要清除所有浏览器缓存。

如果您没有正确配置服务器端的 CORS,并且浏览器缓存响应,则此缓存可能会出现问题。例如:最初配置 CORS 时不允许使用 GET。您发出OPTIONS 请求,浏览器缓存响应,阻止未来的GET 请求。

【讨论】:

感谢您的回答,不明白为什么我无法加载设置 CORS 以允许 AWS 中的所有来源的 svg【参考方案2】:

由于 S3 链接以 // 开头,它将使用当前协议发出请求。如果您有http://localhost,即使AllowedOrigins*,AWS 也不允许您通过http 发出请求。

在 axios url 参数中使用 https 前缀 URL,它应该可以工作。

【讨论】:

以上是关于由于 CORS,无法从 S3 存储桶中获取图像的主要内容,如果未能解决你的问题,请参考以下文章

同一S3存储桶中某些文件的AWS CORS问题

如何从 s3 存储桶中获取 Pyspark 中带有前缀的文件?

如何获取 Rails 应用程序的 CORS 标头以访问 aws s3 存储桶?

获取存储桶中 AWS S3 密钥计数的快速方法

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

使用 boto3 lib 和 AWS Lambda 从 S3 存储桶中的压缩文件中获取数据流