javascript 无法在 Safari 中加载跨域图像(来自 CloudFront)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29418465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 10:30:10  来源:igfitidea点击:

Unable to load cross-origin image (from CloudFront) in Safari

javascriptamazon-s3safariamazon-cloudfront

提问by Robin Pyon

I get the following error when trying to load an image from a CloudFront URL in Safari 8:
Cross-origin image load denied by Cross-Origin Resource Sharing policy.

尝试从 Safari 8 中的 CloudFront URL 加载图像时出现以下错误:
Cross-origin image load denied by Cross-Origin Resource Sharing policy.

This only happens on Safari 8. In FireFox 38 and Chrome 41 latest it loads just fine. (Mac 10.10)

这只发生在 Safari 8 上。在最新的 FireFox 38 和 Chrome 41 中,它加载得很好。(Mac 10.10)

My setup:

我的设置:

1. S3 bucket with the following CORS configuration

1. 具有以下 CORS 配置的 S3 存储桶

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

2. A linked CloudFront distribution

2. 链接的 CloudFront 分配

The following headers have been whitelisted (under behaviours):

以下标题已被列入白名单(在行为下):

  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Origin
  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Origin

3. JavaScript

3. JavaScript

var img = new Image();
img.crossOrigin = '';
img.onload = function() {
  console.log('image loaded');
}


What I've tried:

我试过的:

1. Checking returned headers from curl

1. 检查 curl 返回的标头

The image is returning the correct headers (notably Access-Control-Allow-Origin)

图像返回正确的标题(特别是Access-Control-Allow-Origin

> curl -sI -H 'Origin: localhost' -H 'Access-Control-Request-Method: GET' http://foo.cloudfront.com/image.jpg
...
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Server: AmazonS3
Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
X-Cache: Hit from cloudfront

2. Checking returned headers in the browser

2.在浏览器中检查返回的标题

Interestingly enough the image is NOT returning the Access-Control-Allow-Origin: *header in all three browsers. Why would this be the case?

有趣的是,图像没有Access-Control-Allow-Origin: *在所有三个浏览器中返回标题。为什么会这样?

3. Adding a query string to the URL

3. 在 URL 中添加查询字符串

Adding a query string (e.g. ?foo) to the URL being loaded WILL cause the Access-Control-Allow-Originheader to be returned in the browser, and allows the image to be loaded in Safari! This is great, but why would adding the query string allow this to work (and also return the Access-Control-Allow-Originheader)?

向正在加载的 URL 添加查询字符串(例如 ?foo)将导致Access-Control-Allow-Origin在浏览器中返回标头,并允许在 Safari 中加载图像!这很好,但为什么添加查询字符串会允许它工作(并返回Access-Control-Allow-Origin标题)?

4. Loading an image from an S3 bucket (not tied to a CloudFront distribution)

4. 从 S3 存储桶加载图像(不绑定到 CloudFront 分配)

Loading an image from another bucket not tied to CloudFront (with an identical CORS config) also works just fine in Safari.

从另一个未绑定到 CloudFront 的存储桶(具有相同的 CORS 配置)加载图像在 Safari 中也能正常工作。

Which initially led me to believe this was specifically a CloudFront issue, but the above point with the query string makes me think otherwise.

这最初让我相信这是一个 CloudFront 问题,但上面的查询字符串让我不这么认为。

This is driving me completely batty. Can anyone help shed some light on the above?

这让我完全生气。任何人都可以帮助阐明上述情况吗?



Update

更新

Thanks for the replies. Frustratingly enough, I can't seem to replicate this issue.

感谢您的回复。令人沮丧的是,我似乎无法复制这个问题。

Below is a snippet which loads two images (one from an S3 bucket, another from its respective Cloudfront distribution) and they both also appear to load in just fine with the headers you'd expect, contrary to what I said above in point #2.

下面是一个加载两个图像的片段(一个来自 S3 存储桶,另一个来自其各自的 Cloudfront 发行版),并且它们似乎也可以正常加载您期望的标题,这与我在第 2 点中所说的相反.

Unfortunately I'm not really closer to a definite answer, but for now I'm just going to chalk it down to an error on my behalf, potentially requesting an image before my CORS setup as Derek suggested.

不幸的是,我并没有真正接近确定的答案,但现在我只是代表我将其归结为错误,可能会像德里克建议的那样在我的 CORS 设置之前请求图像。

var img, imgCloudfront;

img = new Image();
img.crossOrigin = '';
img.onload = function() {
  $('body').append('image loaded<br>');
}
img.src = 'http://sandbox-robinpyon.s3.amazonaws.com/test.jpg';

imgCloudfront = new Image();
imgCloudfront.crossOrigin = '';
imgCloudfront.onload = function() {
 $('body').append('image (cloudfront) loaded<br>');
}
imgCloudfront.src = 'http://d32d4njimxij7s.cloudfront.net/test.jpg';
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

采纳答案by Derek

Double checkout your cloudfront behavior settings. Did you add the custom header Origin. It should be Access-Control-Allow-Origin. I recently setup cloudfront as well and found this article helpful: http://kennethjiang.blogspot.com/2014/07/set-up-cors-in-cloudfront-for-custom.html

仔细检查您的 Cloudfront 行为设置。您是否添加了自定义标题Origin。应该是Access-Control-Allow-Origin。我最近也设置了 cloudfront,发现这篇文章很有帮助:http://kennethjiang.blogspot.com/2014/07/set-up-cors-in-cloudfront-for-custom.html

I've had problems with clearing the cache on cloudfront. If you had requested an image before your CORS setup, cloudfront may just return what it had before so your new configurations are not reflected. You can try to run an invalidation, it's one of the cloudfront behavior tabs. I got inconsistent results with this. If you want to make sure it's working, upload a new image and test with that. I'm using rails and on occasion I bump up an asset versions which causes all my asset sto have a new fingerprint and that solves the caching issues because each file has a new name.)

我在清除 cloudfront 上的缓存时遇到了问题。如果您在 CORS 设置之前请求了图像,则 cloudfront 可能会返回它之前的图像,因此不会反映您的新配置。您可以尝试运行失效,它是云前端行为选项卡之一。我得到了不一致的结果。如果您想确保它正常工作,请上传新图像并进行测试。我正在使用 rails,有时我会增加一个资产版本,这会导致我的所有资产都有一个新的指纹,这解决了缓存问题,因为每个文件都有一个新名称。)

Regarding your question about the query string. You probably got a cache miss from cloudfront. You can try to repeat the exercise with curl to see the response X-Cache: Hit from cloudfrontis present or not. In the cloudfront behavior settings there is a config for 'Forward Query Strings'. That may play a factor.

关于您关于查询字符串的问题。您可能从 cloudfront 中遇到缓存未命中。您可以尝试使用 curl 重复练习以查看响应X-Cache: Hit from cloudfront是否存在。在 cloudfront 行为设置中有一个“转发查询字符串”的配置。这可能是一个因素。

In my setup, I had an intermediate varnish cache so I had to mess with that too to make sure all the headers made it through. Doesn't seem like you have that but it's something to watch out for.

在我的设置中,我有一个中间清漆缓存,所以我也不得不处理它以确保所有标题都通过。看起来你没有,但这是需要注意的。

回答by Jakeii

See: https://stackoverflow.com/a/13147554/1994767

参见:https: //stackoverflow.com/a/13147554/1994767

The Access-Control-Allow-Headers (<AllowedHeader>*</AllowedHeader>) header does not allow wildcards. It must be an exact match: http://www.w3.org/TR/cors/#access-control-allow-headers-response-header

Access-Control-Allow-Headers ( <AllowedHeader>*</AllowedHeader>) 标头不允许使用通配符。它必须完全匹配:http: //www.w3.org/TR/cors/#access-control-allow-headers-response-header

回答by Antoine

That's just a guess, but the missing Access-Control-Allow-Originheader seems the key point to me. For some reasons other browsers can do without it but not Safari.
Have you tried tinkering with your CloudFront configuration? Like forwarding all headers instead of whitelisting, or changing query string forwarding setting. And as others have said, please provide a test url so we can check for ourselves.

这只是一个猜测,但缺少的Access-Control-Allow-Origin标题对我来说似乎是关键点。由于某些原因,其他浏览器可以不用它,但 Safari 不行。
您是否尝试过修改 CloudFront 配置?就像转发所有标题而不是白名单,或更改查询字符串转发设置。正如其他人所说,请提供一个测试网址,以便我们自行检查。

回答by wookieb

Try to clean browser cache.

尝试清理浏览器缓存。

If this won't work then please provide the URL to an example image.

如果这不起作用,请提供示例图像的 URL。

回答by Kristian Hanekamp

I am guessing that this is related to the browser cache.

我猜这与浏览器缓存有关。

There is an issue where S3 omits a "Vary: Origin" Header for Non-CORS-Requests. This leads to some browsers caching a Non-CORS response and reusing this cached response in subsequent requests that need CORS, causing the browser to throw the "Cross-origin image load denied by Cross-Origin Resource Sharing policy." error.

存在一个问题,即 S3 省略了非 CORS 请求的“Vary: Origin”标头。这会导致某些浏览器缓存非 CORS 响应并在需要 CORS 的后续请求中重用此缓存的响应,从而导致浏览器抛出“跨域资源共享策略拒绝跨域图像加载”。错误。

For more details see: S3 CORS, always send Vary: Origin

有关更多详细信息,请参阅:S3 CORS,始终发送 Vary: Origin

The problem has also been reported on the AWS S3 Forums

该问题也已在AWS S3 论坛上报告