Pra*_*eek 3 canvas image amazon-s3 amazon-web-services cors
我的应用程序显示存储在AWS S3中的图像(出于安全原因,在私有存储桶中).
为了让用户看到他们的浏览器我生成图像签署的网址一样https://s3.eu-central-1.amazonaws.com/my.bucket/stuff/images/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Date=20170701T195504Z&X-Amz-Expires=900&X-Amz-Signature=bbe277...3358e8&X-Amz-SignedHeaders=host
.
这与<img src="S3URL" />
以下内容完美配合:图像正确显示.
我甚至可以通过复制/粘贴其URL来直接查看另一个标签中的图像.
我也正在生成嵌入这些图像的PDF,这些图像需要先进行转换,然后使用canvas
:resized和watermarked.
但我用于调整大小的库有一些麻烦:
Failed to execute 'getImageData' on 'CanvasRenderingContext2D':
The canvas has been tainted by cross-origin data.
Run Code Online (Sandbox Code Playgroud)
事实上,我们处于CORS环境中,但我已经设置了所有内容,以便可以向用户显示图像,实际上它正在工作.
所以我不确定这个错误的原因:这是另一个CORS安全层:浏览器担心我可能会恶意更改图像吗?
我试图在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>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Run Code Online (Sandbox Code Playgroud)
而且img.crossOrigin = ""
还是img.crossOrigin = "Anonymous"
在客户端,但然后我得到:
Access to Image at 'https://s3.eu-central-1.amazonaws.com/...'
from origin 'http://localhost:5000' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:5000' is therefore not allowed access.
Run Code Online (Sandbox Code Playgroud)
可能缺少哪个AWS/S3端和/或客户端配置?
Mic*_*bot 12
这里的一个解决方法是阻止浏览器缓存下载的对象.这似乎源于S3可以说与Chrome处理缓存对象的方式相互作用的不正确行为.我最近回答了关于服务器故障的类似问题,你可以在那里找到更多细节.
当您从简单的HTML(如<img>
标记)中获取S3中的对象,然后在跨源上下文中再次获取相同的对象时,似乎会出现此问题.
Chrome会缓存第一个请求的结果,然后使用该缓存的响应,而不是第二次发出新请求.当它检查缓存的对象时,没有Access-Control-Allow-Origin
标题,因为它是从不受CORS规则约束的请求缓存的...所以当第一个请求发出时,浏览器没有发送Origin
标题.因此,S3没有响应Access-Control-Allow-Origin
头(或任何与CORS相关的头).
问题的根似乎与HTTP Vary:
响应头有关,它与缓存有关.
Web服务器(在这种情况下为S3)可以使用Vary:
响应头向浏览器发信号通知服务器能够生成多个返回对象的表示 - 如果浏览器改变了请求的属性,回应可能不同.当浏览器考虑使用缓存对象时,它应该在得出缓存对象适合当前需要之前检查对象在新上下文中是否有效.
实际上,当您向Origin
S3 发送请求标头时,您会收到包含的响应Vary: Origin
.这告诉浏览器,如果请求中发送的源是不同的值,则响应也可能不同 - 例如,因为并非所有源都可能被允许.
底层问题的第一部分是S3 - 可以说 - 应该总是Vary: Origin
在桶上配置CORS时返回,即使浏览器没有发送原始头,因为Vary
可以根据你实际上没有实际的头来指定在请求中包含,告诉您如果包含它,响应可能会有所不同.但是,当Origin
它不存在时,它不会那样做.
问题的第二部分是Chrome - 当它查询其内部缓存时 - 看到它已经拥有该对象的副本.播放缓存的响应不包括在内Vary
,因此Chrome假定此对象对CORS请求也完全有效.显然,事实并非如此,因为当Chrome尝试使用该对象时,它会发现缺少跨源响应标头.据推测,如果Chrome Vary: Origin
在原始请求中收到了S3 的响应,它会意识到包含第二个请求的临时请求标头Origin:
,因此它会正确地获取该对象的不同副本.如果它这样做,问题就会消失 - 正如我们通过设置Cache-Control: no-cache
对象所示,阻止Chrome缓存它.但是,事实并非如此.
因此,我们通过Cache-Control: no-cache
在S3中设置对象来解决这个问题,以便Chrome不会缓存第一个,并且会为第二个请求发出正确的CORS请求,而不是尝试使用缓存的副本,这将失败.
请注意,如果要避免在S3中更新对象以包含Cache-Control: no-cache
响应,则可以使用另一个选项来解决此问题,而无需在S3中实际将标题添加到静止的对象中.实际上,还有两个选择:
S3 API遵循查询字符串中传递的值response-cache-control=no-cache
.将此添加到签名URL将指示S3将标头添加到响应,而不管Cache-Control
与对象一起存储的元数据值(或缺少该元素值).您不能简单地将此附加到查询字符串 - 您必须将其添加为URL签名过程的一部分.但是,一旦将其添加到代码中,您的对象将Cache-Control: no-cache
在响应标头中返回.
或者,如果您在呈现页面时可以单独为同一对象生成这两个签名URL,则只需更改其中一个签名URL相对于另一个签名URL的到期时间.让它延长一分钟,或沿着这些线.将到期时间从一个更改为另一个将强制两个签名的URL不同,并且Chrome将两个不同的对象与两个不同的查询字符串解释为两个单独的对象,这也应该消除第一个缓存对象的错误使用为其他请求服务.
归档时间: |
|
查看次数: |
1508 次 |
最近记录: |