59

在 chrome 22 和 safari 6 中。

使用启用 CORS 的 S3 存储桶从 s3 加载图像以在画布中使用(将提取作为主要意图),代码如下:

<!-- In the html -->
<img src="http://s3....../bob.jpg" /> 

// In the javascript, executed after the dom is rendered
this.img = new Image();
this.img.crossOrigin = 'anonymous';
this.img.src = "http://s3....../bob.jpg";

我观察到以下情况:

  1. 禁用缓存
  2. 一切正常,两个图像都加载

然后尝试启用缓存:

  1. 启用缓存
  2. DOM 图像加载,画布图像创建 dom 安全异常

如果我修改代码的 javascript 部分以附加查询字符串,如下所示:

this.img = new Image();
this.img.crossOrigin = 'anonymous';
this.img.src = "http://s3....../bob.jpg?_";

一切正常,即使完全启用缓存。通过使用 http 代理并观察到在失败的情况下,实际上并没有从服务器请求图像,我了解到缓存是一个问题。

我不得不得出的结论是图像缓存正在保存原始请求标头,然后将其用于后续启用 CORS 的请求 - 由于违反同源策略而产生了安全异常。

这是预期的行为吗?

编辑:在 Firefox 中工作。

Edit2: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>
    </CORSRule>
</CORSConfiguration>

我正在使用全开,因为我现在只是在本地盒子上进行测试。这还没有生产。

Edit3:更新了 cors 政策以指定来源

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

已验证的传出标头:

Origin  http://localhost:5000
Accept  */*
Referer http://localhost:5000/builder
Accept-Encoding gzip,deflate,sdch
Accept-Language en-US,en;q=0.8
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.3

传入标头:

Access-Control-Allow-Origin http://localhost:5000
Access-Control-Allow-Methods    GET
Access-Control-Allow-Credentials    true

如果我在加载到画布时没有破坏缓存,chrome 仍然会失败。

编辑4:

刚刚在失败案例中注意到了这一点。

传出标头:

GET /373c88b12c7ba7c513081c333d914e8cbd2cf318b713d5fb993ec1e7 HTTP/1.1
Host    amir.s3.amazonaws.com
User-Agent  Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.91 Safari/537.4
Accept  */*
Referer http://localhost:5000/builder
Accept-Encoding gzip,deflate,sdch
Accept-Language en-US,en;q=0.8
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.3
If-None-Match   "99c958e2196c60aa8db385b4be562a92"
If-Modified-Since   Sat, 29 Sep 2012 13:53:34 GMT

传入标头:

HTTP/1.1 304 Not Modified
x-amz-id-2  3bzllzox/vZPGSn45Y21/vh1Gm/GiCEoIWdDxbhlfXAD7kWIhMKqiSEVG/Q5HqQi
x-amz-request-id    48DBC4559B5B840D
Date    Sat, 29 Sep 2012 13:55:21 GMT
Last-Modified   Sat, 29 Sep 2012 13:53:34 GMT
ETag    "99c958e2196c60aa8db385b4be562a92"
Server  AmazonS3

认为这是第一个请求,由 dom 触发。我不知道这不是javascript请求。

4

3 回答 3

15

问题是图像是从以前的请求中缓存的,没有所需的 CORS 标头。因此,当您再次请求它时,对于画布,指定了“crossorigin”,浏览器使用缓存版本,看不到必要的标头,并引发 CORS 错误。当您将“?_”添加到 url 时,浏览器会忽略缓存,因为这是另一个 URL。看看这个线程: https ://bugs.chromium.org/p/chromium/issues/detail?id=409090

Firefox 和其他浏览器没有这个问题。

于 2016-05-26T08:09:56.923 回答
6

所描述的行为似乎是合乎逻辑的,因为缓存条目键是目标 URI(请参阅7234 超文本传输​​协议(HTTP/1.1):缓存)。要解决此问题并有效使用缓存,您需要使图像托管服务器在两种情况下都给出相同的响应。

一种选择是让用户代理Origin在第一个请求中也发送 HTTP 标头(假设带有键targetUri的响应尚未在缓存中):

<img src="targetUri" crossorigin="anonymous" />

另一种选择是配置图像托管服务器以发送与 CORS 相关的 HTTP 标头,无论请求是否包含OriginHTTP 标头。有关更多信息,请参阅S3 CORS,请始终在 StackOverflow 上发送 Vary: Origin讨论。

您还可以使用响应 HTTP 标头通知用户代理响应对Origin请求 HTTP 标头敏感Vary。缺点是用户代理可能Vary仅将标头用作响应验证器(而不是作为缓存条目键的一部分)并且仅存储目标 URI 的单个响应实例,这使得更难有效地使用缓存。有关更多信息,请查看Mark Nottingham 重新访问的文章浏览器缓存状态。

于 2018-07-27T11:14:52.490 回答
0

您应用了哪些 CORS 设置?This post建议解析AllowedOrigin通配符(而不是逐字发送,这似乎是未记录的行为);然后为后续请求缓存标头值,从而导致类似于您报告的问题。Access-Control-Allow-Origin

于 2012-09-29T01:09:25.660 回答