3

canvas 污染问题

 1 year ago
source link: https://icodex.me/tainted_canvas/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

canvas 污染问题

2022年6月29日 · One min read
Front End Engineer

前端时间实现了一个用canvas往模板图片绘制数据的功能点,遇到了一个跨域引起canvas污染的问题,仔细发掘下去发现不少的技术点。

tainted canvas

对于canvas污染的问题,这应该是非常常见的在处理跨域资源时会遇到的问题。

一般来说,利用canvas绘制图像的时候需要执行以下步骤:

  1. 创建canvas元素;
  2. 获取canvas元素的二维渲染上下文对象;
  3. 创建Image对象并加载;
  4. 等待图像加载完成的时候绘制在canvas
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

const img = new Image();
img.src = 'xxxx';
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;

canvas.drawImage(img, 0, 0);
}

当使用drawImage方法绘制一个不同源的图像时,此时并不会报错,但是canvas会变成tainted (被污染),之后如果在当前被污染的canvas上调用以下方法时就会抛出SecurityError的错误。

caution
  • HTMLCanvasElement.toDataURL()
  • HTMLCanvasElement.toBlob()
  • CanvasRenderingContext2D.getImageData()

Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

为什么会出现 tainted canvas

tainted canvas 其实还是牵扯到浏览器同源策略的限制问题,一般来说这个问题在使用XMLHttpRequest或者Fetch发起网络请求的情况比较多见,而在这里的目的是禁止使用canvas随意从另一个网站加载图片再转换成数据的强盗行为。

这看起来合情合理,但是现在大型网站一般都会走 CDN 服务器来缓存并代理资源访问,这就导致在动态加载图像的时候实际可能走的是 CDN 服务器域名,这就导致网页域名和资源域名不同源了。本来防别人的,这下连自己人也堵在外面了。

CORS + crossOrigin

要解决以上问题,需要两步操作:

  1. 配置服务端响应头支持跨域请求的域名,请求方法等;
  2. 设置crossorigin属性

cors header 配置

关于服务端 CORS 的配置就不细说了,具体的可以看我的这篇文章:

跨域直通车 —— 跨域与解决方案 | icodex

crossorigin

HTML 规范给crossorigin制定了三个允许值

  • anonymous""(空字符串):匿名请求访问资源,不会在跨域请求的时候携带任何身份凭据
  • use-credentials:在跨域请求的时候携带身份凭据

值得一提的是,crossorigin无论设置成哪一个值都会指定浏览器以跨域的模式请求资源,发送相关跨域请求头,并检查跨域请求响应头等;但是为了客户端安全考虑,一般设置成anonymous更为合适,避免向陌生的服务端发送网页的cookie等身份数据。

以下资源可能需要crossorigin来取得数据访问权:

元素限制
img, audio, video当它们被放在canvas元素内部使用时
script使用 window.onerror
link

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK