缓存图像的CORS策略

ami*_*rpc 46 javascript html5 canvas amazon-s3 cross-domain

在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";
Run Code Online (Sandbox Code Playgroud)

我观察到以下情况:

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

然后在启用缓存的情况下尝试:

  1. 启用缓存
  2. DOM图像加载,画布图像创建一个dom安全例外

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

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

一切正常,即使完全启用了缓存.我通过使用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>
Run Code Online (Sandbox Code Playgroud)

我正在使用大开放,因为我现在只是从我当地的盒子进行测试.这还没有投入生产.

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>
Run Code Online (Sandbox Code Playgroud)

已验证的传出标题

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
Run Code Online (Sandbox Code Playgroud)

传入标题:

Access-Control-Allow-Origin http://localhost:5000
Access-Control-Allow-Methods    GET
Access-Control-Allow-Credentials    true
Run Code Online (Sandbox Code Playgroud)

如果我在加载到画布时没有破坏缓存,则仍然无法使用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
Run Code Online (Sandbox Code Playgroud)

传入标题:

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
Run Code Online (Sandbox Code Playgroud)

认为这是由dom引发的第一个请求.我不知道它不是javascript请求.

小智 10

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

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


Leo*_*lev 6

描述的行为似乎合乎逻辑,因为缓存条目键是目标 URI(请参阅7234 Hypertext Transfer Protocol (HTTP/1.1): Caching)。为了解决这个问题并有效地使用缓存,您需要让图像托管服务器在两种情况下都给出相同的响应。

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

<img src="targetUri" crossorigin="anonymous" />
Run Code Online (Sandbox Code Playgroud)

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

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


o.v*_*.v. 0

您正在应用什么 CORS 设置?这篇文章建议解析AllowedOrigin中的通配符(而不是逐字发送,这似乎是未记录的行为);然后标头值会被缓存以用于后续请求,从而导致与您报告的问题类似的问题。Access-Control-Allow-Origin