📜  为什么 canvas.toDataURL() 会抛出安全异常?

📅  最后修改于: 2022-05-13 01:56:52.215000             🧑  作者: Mango

为什么 canvas.toDataURL() 会抛出安全异常?

Canvas.toDataURL(): canvas.toDataURL() 方法返回 Web 资源的 URI(统一资源标识符)。它由默认值为 PNG 的 type 参数指定的格式描述的图像组成。

句法:

Canvas.toDataURL(type, encoderOptions);
  • type:它是一个可选属性,包含关于图像格式的 DOMString 注释。它的默认值为 PNG。
  • encoderOptions :它由一个介于 0 和 1 之间的数值组成,用于指示用于各种图像格式的图像质量。其默认值为 0.92。

安全异常:如果画布元素不是原始干净的,即如果未设置其原始干净标志,则会引发安全异常。 (错误的)。换句话说,如果画布元素包含外来内容,则安全性受到威胁,并发生 SECURITY_ERR 异常。当画布被用于绘制数据而不遵循与源相关的规则并且没有使用CORS(跨域资源共享)机制时,它就会被污染。受污染的画布不被认为是安全的。尝试从画布中检索图像数据将导致安全异常指示的失败。与 toDataURL() 一起,调用 toBlob() 和 getImageData() 等方法也会导致类似类型的错误。
这些例外用于保护用户不会在未经他们事先许可的情况下暴露他们的私人数据。由于图像可用于从网站捕获信息,因此必须使用异常。

示例: Canvas 元素产生异常。

Javascript
function getBase64FromImageUrl(URL) {
    var img = new Image();
    img.src = URL;
    img.onload = function () {
  
        var canvas = document.createElement("canvas");
        canvas.width = this.width;
        canvas.height = this.height;
  
        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);
  
        var dataURL = canvas.toDataURL("image/png");
  
         
alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
  
    };
}


输出:当尝试在画布上操作未经授权在代码中处理的图像时,会发生此类安全错误。这些错误是由服务器已批准的请求的 Access-Control-Allow-Origin 标头引起的。由于图像属于另一个域,大多数浏览器在访问它们时会出现异常,从而导致重大安全漏洞。

Uncaught Security Error: Failed to execute ‘toDataURL’ on 
‘HTMLCanvasElement’: tainted canvases may not be exported.

上述问题的解决方案:图像有一个称为 crossorigin 的属性,该属性在 HTML 中指定,通过将其与合适的 CORS 标头组合,它可以从外部来源加载以在画布中使用,其行为就像属于当前来源一样。如果未获得 CORS 批准,则画布将被污染,并且没有任何规定可以将数据从画布中拉回。因此,像toBlob()toDataURL()getImageData()这样的方法不能在不引发安全错误的情况下使用。可以通过使用 Javascript 或 HTML 设置图像的 crossorigin 属性来防止这些错误

例子:

  • HTML:

  • JavaScript:
var image = new Image();
  image.crossOrigin = "Anonymous";
  ...

注意:此方法仅在服务器响应具有以下 Access-Control-Allow-Origin 标头时才有效。否则,来自“otherdomain.com”的图像将被跨域资源共享策略阻止加载。

由于问题是图像不属于当前域,因此可以创建具有服务器语言的代理,类似于在 HTTPS 内容上显示 HTTP 内容,从而提供安全的环境。