无法在 Safari 中加载跨域图像(来自 CloudFront)
Posted
技术标签:
【中文标题】无法在 Safari 中加载跨域图像(来自 CloudFront)【英文标题】:Unable to load cross-origin image (from CloudFront) in Safari 【发布时间】:2015-06-07 17:36:19 【问题描述】:在 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 问题,但上面的查询字符串让我不这么认为。
这让我彻底崩溃了。任何人都可以帮助阐明上述内容吗?
更新
感谢您的回复。令人沮丧的是,我似乎无法复制这个问题。
下面是一个 sn-p,它加载了两个图像(一个来自 S3 存储桶,另一个来自其各自的 Cloudfront 发行版),并且它们似乎都可以很好地加载您所期望的标题,这与我所说的相反上面第 2 点。
不幸的是,我并没有真正接近一个明确的答案,但现在我只是代表我将其归结为一个错误,可能会按照 Derek 的建议在我的 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>
【问题讨论】:
如果图像在除 safari 8 之外的所有浏览器中都能正常渲染,则问题不应该出现在图像末尾。能否提供图片地址试用一下?? 经过几个小时的痛苦,我看到了你的帖子,并在我的图片 src 中添加了“?foo=bar”,它在 safari 9 中解决了这个问题。今天的技术让我失望了。 【参考方案1】:仔细检查您的云端行为设置。您是否添加了自定义标头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
是否存在。在云端行为设置中有一个“转发查询字符串”的配置。这可能是一个因素。
在我的设置中,我有一个中间清漆缓存,因此我也不得不对其进行处理以确保所有标头都能通过。您似乎没有,但需要注意。
【讨论】:
我确实添加了自定义标题Origin
。有趣的是,只有三个标题可供我使用白名单,Access-Control-Request-Headers
、Access-Control-Request-Method
和 Origin
。没有像那篇文章建议的那样将Access-Control-Allow-Origin
列入白名单。由于我无法重现此问题,因此我倾向于认为这是 Cloudfront 上的错误配置,尽管它并不能真正解释 Safari 问题。
对,您可以选择的标题不包括Access-Control-*
的标题,但您可以将它们作为自定义标题输入。看来你已经解决了这个问题:)。
很奇怪,对我来说它只是一个过滤器。输入新的自定义标题不起作用。希望我没有遗漏一些完全明显的东西?见:i.imgur.com/wsRioer.png
是的,这很奇怪。我也看了一些配置。当源类型为 S3 Origin
时,它缺少一个 Add Custum >>
按钮,就像在 cl.ly/image/0o1d3j3K2X1Z 中一样,它被设置为从另一个网站提取的自定义源。【参考方案2】:
见:https://***.com/a/13147554/1994767
Access-Control-Allow-Headers (<AllowedHeader>*</AllowedHeader>
) 标头不允许使用通配符。必须完全匹配:http://www.w3.org/TR/cors/#access-control-allow-headers-response-header
【讨论】:
【参考方案3】:这只是一个猜测,但缺少的 Access-Control-Allow-Origin
标题对我来说似乎是关键点。由于某些原因,其他浏览器可以不用它,但 Safari 不行。
您是否尝试过修改 CloudFront 配置?就像转发所有标头而不是白名单一样,或者更改查询字符串转发设置。正如其他人所说,请提供一个测试网址,以便我们自己检查。
【讨论】:
我已经用一个加载这些 URL 的 sn-p 更新了我的问题。此测试示例运行良好,并且正如您所期望的那样,所有浏览器都返回了Access-Control-Allow-Origin
标头。如上所述,很可能是我在请求图像后更新了我的 Cloudfront 配置...... arg..【参考方案4】:
尝试清理浏览器缓存。
如果这不起作用,请提供示例图片的 URL。
【讨论】:
【参考方案5】:我猜这与浏览器缓存有关。
存在一个问题,即 S3 为非 CORS 请求省略了“Vary: Origin”标头。这会导致一些浏览器缓存一个 Non-CORS 响应,并在后续需要 CORS 的请求中重用这个缓存的响应,导致浏览器抛出“Cross-origin image load denied by Cross-Origin Resource Sharing policy”。错误。
更多详情见:S3 CORS, always send Vary: Origin
这个问题也已经在AWS S3 Forums上报告了
【讨论】:
以上是关于无法在 Safari 中加载跨域图像(来自 CloudFront)的主要内容,如果未能解决你的问题,请参考以下文章
instagram 图像无法在 Opera mini 中加载/显示
无法使用 WKWebView 在 Safari 中打开外部链接
Amazon S3 图像,无法使用 html5 画布保存,出现受污染的画布错误
来自html字符串的iOS Swift 4图像未在WKWebView中加载
Graphiql (GraphQL UI) 无法在 Chrome 中加载,但在 Firefox 和 Safari 中有效