简体   繁体   English

JavaScript:toDataUrl()抛出“安全错误:可能无法导出受污染的画布”。

[英]JavaScript: toDataUrl() throwing “Security Error: Tainted canvases may not be exported.”

I have an HTML5 canvas on which I draw an image from an svg. 我有一个HTML5画布,我从svg中绘制一个图像。

HTML HTML

<canvas id="canvas" width="600" height="320"></canvas>

JavaScript JavaScript的

var DOMURL = window.URL || window.webkitURL || window;

var data = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="320">'+
                    '<foreignObject width="100%" height="100%">'+
                        '<style>'+
                             'foreignObject {'+
                                 'background-color: #000;'+
                                 'color: #fff'+
                                 'border-radius: 10px;'+
                             '}'+
                            'h1 {'+
                                'color: #2acabd;'+
                                'font: 25px arial;'+
                                'font-weight: bold;'+
                                'text-align: center;'+
                            '}'+
                            'h2 {'+
                                'margin: 0;'+
                                'color: #2acabd;'+
                                'font: 15px arial;'+
                            '}'+
                            'p {'+
                                'color: #fff;'+
                            '}'+
                        '</style>'+
                        '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size: 40px;">'+
                            '<h1>Heading</h1>'+
                            '<div>'+
                                '<div id="details-wrapper">'+
                                    '<h2>Full Name</h2>'+
                                    '<p>Alan Johnson</p>'+

                                    '<h2>Date of Birth</h2>'+
                                    '<p>7th November 1988</p>'+

                                    '<p><span id="user-id">34329483028493284093284432</span></p>'+
                                '</div>'+
                            '</div>'+
                        '</div>'+
                    '</foreignObject>'+
                '</svg>';


var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
img = new Image();
img.setAttribute("crossOrigin", "anonymous");
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);

img.onload = function() {
  ctx.drawImage(img, 0, 0);
  DOMURL.revokeObjectURL(url);
  console.log(canvas.toDataURL());
}
img.src = url;

(JS Fiddle: https://jsfiddle.net/LondonAppDev/qnpcg8th/1/ ) (JS小提琴: https//jsfiddle.net/LondonAppDev/qnpcg8th/1/

When I call canvas.toDataURL() , I am getting the exception: 当我调用canvas.toDataURL() ,我得到了异常:

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

I have seen the many other questions and answers on Stack Overflow relating to this exception. 我已经在Stack Overflow上看到了与此异常相关的许多其他问题和答案。 My problem is different, because (as you can see) I am not at any point including any images from another domain in my svg or canvas. 我的问题是不同的,因为(正如你所看到的)我不是在任何一点,包括我的svg或画布中来自另一个域的任何图像。

I am guessing the problem is that I am creating an object URL with DOMURL.createObjectURL . 我猜测问题是我正在使用DOMURL.createObjectURL创建一个对象URL。

I am aware that there are some compatibility issues with doing this in different browsers, however this app only needs to run in Chrome. 我知道在不同的浏览器中执行此操作存在一些兼容性问题,但此应用只​​需要在Chrome中运行。 Also, drawing the text directly onto the canvas is not an option, I must do it via an svg. 此外,直接将文本绘制到画布上是不可取的,我必须通过svg来完成。

Any ideas as to how I can get around this issue, and successfully get a PNG of my canvas? 关于如何解决这个问题,并成功获得我的画布的PNG的任何想法?

I solved this by converting the svg to a data URL instead of a Blob. 我通过将svg转换为数据URL而不是Blob来解决这个问题。

I removed var url = DOMURL.createObjectURL(svg); 我删除了var url = DOMURL.createObjectURL(svg); and replaced img.src = url; 并替换了img.src = url; with this: 有了这个:

function buildSvgImageUrl(svg) {
    b64 = window.btoa(svg);
    return "data:image/svg+xml;base64," + b64;
}

img.src = buildSvgImageUrl(data);

Now it works flawlessly. 现在它完美无缺。

This is was for security and user privacy reasons. 出于安全和用户隐私的原因。
To paint a <foreignObject> on a canvas can leaks several informations about users, and until then, chrome team thought they didn't had enough security measures to prevent this so they did taint the canvas. 在画布上绘制<foreignObject>可能会泄漏有关用户的几个信息,在此之前,chrome团队认为他们没有足够的安全措施来防止这种情况,因此他们确实污染了画布。

Here is the chromium bug report about this issue. 以下是有关此问题的铬虫报告

But as OP found out, they had an implementation bug that forgot to set this restriction on dataURI versions. 但是当OP发现时,他们有一个实现错误,忘记在dataURI版本上设置这个限制。
I did post this bug report about the fact that they do not taint canvas with dataURIs. 我发布了这个错误报告 ,说明他们没有使用dataURI污染画布。

All this lead to the leverage of the former restrictions, so in next versions of chrome, we should be able to paint <foreignObject> on canvas without tainting it, even with BlobURIs. 所有这些都导致了前一个限制的影响,因此在下一版本的chrome中,我们应该能够在画布上绘制<foreignObject>而不会污染它,即使使用BlobURI也是如此。

But note that Safari still does have the same restriction (without the implementation bug, ie the dataURI hack doesn't work there), and that IE < Edge do not support <foreignObject> element and taints the canvas when any SVG has been painted to it, and that FF does remove all UserAgent and OS styles (which leads to different results than the one you could expect). 但请注意,Safari仍然具有相同的限制(没有实现错误,即dataURI hack在那里不起作用),并且IE <Edge不支持<foreignObject>元素并且当任何 SVG被绘制到时会污染画布它确实删除了所有UserAgent和OS样式(导致与您期望的结果不同的结果)。

A real workaround then is to not use this hack to get your elements painted, but draw all your HTML with CanvasAPI drawing methods (just like html2canvas does). 一个真正的解决方法是不使用这个hack来绘制你的元素,而是使用CanvasAPI绘图方法绘制所有HTML(就像html2canvas那样)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么收到错误“未捕获的SecurityError:无法在&#39;HTMLCanvasElement&#39;上执行&#39;toDataURL&#39;:错误的画布可能无法导出。 ” - Why am I getting the error “Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. ” Canvas.toDataURL() 受污染的画布可能无法导出 - Canvas.toDataURL() Tainted canvases may not be exported 从视频提升创建的画布“可能无法导出受污染的画布。” 保存时出错 - Canvas that created from video raising "Tainted canvases may not be exported." error when saving DOMException:无法在“HTMLCanvasElement”上执行“toDataURL”:可能无法导出受污染的画布 - DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported 未捕获的 DOMException:无法在“HTMLCanvasElement”上执行“toDataURL”:可能无法导出受污染的画布 - Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported 受污染的画布不得出口 - Tainted canvases may not be exported 带有 React 的 Tesseract.js:受污染的画布可能无法导出 - Tesseract.js with React: Tainted canvases may not be exported 离线版本的 HTML2canvas - 受污染的画布可能无法导出 - HTML2canvas in offline version - Tainted canvases may not be exported 可能无法导出空白的PNG /污染的画布(不使用图像) - Blank PNG / Tainted canvases may not be exported (not using images) Chrome:受污染的画布可能无法导出; 仅限离线应用 - Chrome: Tainted canvases may not be exported; Offline-only app
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM