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

时间:2015-04-02 17:02:29

标签: javascript amazon-s3 safari amazon-cloudfront

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

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

我的设置:

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。链接的CloudFront分配

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

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

第3。的JavaScript

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

我尝试过的事情:

1。检查curl返回的标题

图片返回正确的标题(特别是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。检查浏览器中返回的标题

有趣的是,图片并没有在所有三个浏览器中返回Access-Control-Allow-Origin: *标头。为什么会出现这种情况?

第3。将查询字符串添加到URL

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

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

从另一个与CloudFront无关的存储桶(具有相同的CORS配置)加载图像在Safari中也可以正常工作。

最初让我相信这是一个特别是CloudFront问题,但上面的查询字符串让我想到了。

这让我完全沮丧。任何人都可以帮助阐明上述内容吗?


更新

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

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

不幸的是,我并没有真正接近一个明确的答案,但是现在我只是想把它归结为我的错误,可能会在我的CORS设置之前请求一张图片,如Derek建议的那样。

&#13;
&#13;
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';
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
&#13;
&#13;
&#13;

5 个答案:

答案 0 :(得分:7)

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

我在清除云端缓存方面遇到了问题。如果您在CORS设置之前请求了图像,那么Cloudfront可能会返回之前的图像,因此您的新配置不会被反映出来。您可以尝试运行失效,它是云端行为标签之一。我得到了不一致的结果。如果您想确保它正常工作,请上传新图片并进行测试。我使用rails并且偶尔会提升资产版本,这会导致我的所有资产都有新的指纹并解决了缓存问题,因为每个文件都有一个新名称。)

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

在我的设置中,我有一个中间清漆缓存,所以我不得不弄乱它,以确保所有标头通过。看起来你没有这个但是需要注意的事项。

答案 1 :(得分:5)

请参阅:https://stackoverflow.com/a/13147554/1994767

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

尝试清理浏览器缓存。

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

答案 4 :(得分:1)

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

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

有关详细信息,请参阅:S3 CORS, always send Vary: Origin

AWS S3 Forums

也报告了这个问题