带有CORS标头的受污染HTML画布 [英] Tainted HTML Canvas even with CORS headers

查看:131
本文介绍了带有CORS标头的受污染HTML画布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取图像的数据URL。该图像来自跨源远程服务器Wikipedia。我使用此JavaScript尝试执行此操作:

I'm trying to get the data URL for an image. The image is coming from a cross origin remote server, Wikipedia. I use this JavaScript to try to do it:

# get the image
const img = document.createElement('img')
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Strychnine.svg/360px-Strychnine.svg.png'
# don't send credentials with this request
img.crossOrigin = 'anonymous'
# now copy to a <canvas /> to get data URL
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx  = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
canvas.toDataURL('image/jpg')

但是我遇到此错误:未捕获的DOMException:无法在'HTMLCanvasElement'上执行'toDataURL':可能无法导出污染的画布

我读到这是一个CORS问题。如果服务器未设置 Access-Control-Allow-Origin 标头,则浏览器将阻止您从图像中获取图像数据。 但是这很奇怪。我检查了响应,并设置了标头。所以我不明白为什么这行不通。这是我从终端发出请求时的输出(标题与Chrome devtools中显示的标题相同)。

I read that this is a CORS issue. The browser prevents you from getting the image data from images if the server hadn't set the Access-Control-Allow-Origin header. But here's the weird thing. I checked the response and that header is set. So I don't understand why this isn't working. Here's the output when I make the request from the terminal (headers are the same from what was shown in the Chrome devtools).

$ http 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Strychnine.svg/360px-Strychnine.svg.png'

HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Age, Date, Content-Length, Content-Range, X-Content-Duration, X-Cache, X-Varnish
Age: 6359
Connection: keep-alive
Content-Disposition: inline;filename*=UTF-8''Strychnine.svg.png
Content-Length: 11596
Content-Type: image/png
Date: Fri, 29 Dec 2017 21:00:31 GMT
Etag: 223fb180fc10db8693431b6ca88dd943
Last-Modified: Sun, 04 Sep 2016 09:13:24 GMT
Strict-Transport-Security: max-age=106384710; includeSubDomains; preload
Timing-Allow-Origin: *
Via: 1.1 varnish-v4, 1.1 varnish-v4, 1.1 varnish-v4, 1.1 varnish-v4
X-Analytics: https=1;nocookies=1
X-Cache: cp1049 hit/4, cp2022 pass, cp4026 hit/4, cp4024 hit/3
X-Cache-Status: hit-front
X-Client-IP: 2606:6000:670c:f800:989:be22:e59d:3c3f
X-Object-Meta-Sha1Base36: 1xx5tvhafvp54zfrfx5uem0vazzuo1a
X-Timestamp: 1472980403.52438
X-Trans-Id: tx154e595e211c449d95b3d-005a469417
X-Varnish: 474505758 476375076, 160459070, 709465351 725460511, 931215054 920521958

所以为什么不这行不通吗?

So why isn't this working? Is something else required for my canvas not to be "tainted"?

推荐答案

当您设置 src 在您的图片上,浏览器会请求该图片。但是到那时,您还没有设置 img.crossOrigin 。将 img.crossOrigin 行移到 img.src 行上方。

When you set src on your image, the browser makes a request for the image. But at that point, you haven't yet set img.crossOrigin. Move the img.crossOrigin line above the img.src line.

这可以解决受污染的画布问题,但是您仍然不会获得URL。图像请求是异步的。您正在尝试使用尚未加载的图像绘制到画布上。将其余代码移到图像上的 load 处理程序中,并将 img.src 行结尾开始整个过程​​:

That fixes the tainted canvas problem, but you still won't get your URL. The request for the image is asynchronous. You're trying to draw to the canvas with an image that hasn't loaded yet. Move the rest of the code into a load handler on your image and put the img.src line at the end to kick the whole thing off:

const img = document.createElement('img');
img.crossOrigin = 'anonymous';
img.addEventListener('load', () => {
  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);
  console.log(canvas.toDataURL('image/jpg'));
});
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Strychnine.svg/360px-Strychnine.svg.png';

这篇关于带有CORS标头的受污染HTML画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆