被跨域数据污染的画布

IT技术 javascript canvas cross-domain cors mjpeg
2021-02-23 19:06:24

我正在从我可以信任的第三方站点加载动态 jpeg。我正在尝试,getImageData()但浏览器 (Chrome 23.0) 抱怨:

Unable to get image data from canvas because the canvas has been tainted by
cross-origin data.

SO上有一些类似的问题,但他们使用的是本地文件,而我使用的是第三方媒体。我的脚本在共享服务器上运行,我不拥有远程服务器。

我尝试过img.crossOrigin = 'Anonymous'img.crossOrigin = ''(请参阅Chromium 博客上关于 CORS 的这篇文章),但没有帮助。关于如何getImageData在具有跨域数据的画布上的任何想法谢谢!

4个回答

一旦被污染,您就无法重置 crossOrigin 标志,但如果您事先知道图像是什么,您可以将其转换为数据 URL,请参阅 将图像从数据 URL 绘制到画布

但是不,您不能也不应该使用来自不支持 CORS 的外部来源的 getImageData()

这是关于 CORS 支持的相当全面的指南html5rocks.com/en/tutorials/cors是的,这是一个很大的安全问题。
2021-04-25 19:06:24
感谢回复。不确定我们是否可以申请toDataURL()mjpeg,但我会尝试一下。为什么没有?安全原因?有没有具体配置外部服务器应该做什么?或者即使他们没有那个配置,我也可以使用 toDataURL 来做到这一点。
2021-04-29 19:06:24
即使使用 CORS 这也可以工作吗?我还没有成功。
2021-05-05 19:06:24
我怎么事先知道想象一下你有一个<img>标签,但你不知道它是什么......你怎么知道你是否可以绘制它或者是否需要使用 加载它crossorigin="anonymous"
2021-05-13 19:06:24
@TomášZato 你没有,因为这正是 CORS 试图阻止的。它应该只被允许如果你手头的形象是什么之前知道,如果它是安全的。
2021-05-13 19:06:24

虽然这个问题很老,但问题仍然存在,而且网络上几乎没有可以解决的问题。我想出了一个我想分享的解决方案:

您可以先使用不设置crossorigin属性的图像(或视频),然后测试您是否可以通过 AJAX 获得对同一资源的 HEAD 请求。如果失败,您将无法使用该资源。如果成功,您可以添加该属性并使用附加的时间戳重新设置图像/视频的源以重新加载它。

此解决方法允许您向用户显示您的资源,如果不支持 CORS,则只需隐藏一些功能。

HTML:

<img id="testImage" src="path/to/image.png?_t=1234">

JavaScript:

var target = $("#testImage")[0];
    currentSrcUrl = target.src.split("_t=").join("_t=1"); // add a leading 1 to the ts
$.ajax({
    url: currentSrcUrl,
    type:'HEAD',
    withCredentials: true
})
.done(function() {
    // things worked out, we can add the CORS attribute and reset the source
    target.crossOrigin = "anonymous";
    target.src = currentSrcUrl;
    console.warn("Download enabled - CORS Headers present or not required");
    /* show make-image-out-of-canvas-functions here */
})
.fail(function() {
    console.warn("Download disabled - CORS Headers missing");
    /* ... or hide make-image-out-of-canvas-functions here */
});

在 IE10+11 和当前的 Chrome 31、FF25、Safari 6(桌面)中测试和工作。在 IE10 和 FF 中,当且仅当您尝试从 https 脚本访问 http 文件时,您可能会遇到问题。我还不知道有什么解决方法。

2014 年 1 月更新:

为此所需的 CORS 标头应如下所示(Apache 配置语法):

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"

仅 ajax 请求需要 x-header。据我所知,大多数浏览器都没有使用它

旧答案,但请注意,相反的方法似乎更容易:首先设置 img 标签的 crossOrigin,监听其error事件处理程序,设置远程 src,如果它触发,你知道你会污染画布。
2021-05-02 19:06:24
感谢回复。因此,对于“工作”,您的意思是人们可以getImageData在此外部资源上做些什么?如果我们按照您提到的方法进行解决。
2021-05-11 19:06:24

同样值得注意的是,如果您在本地工作,无论资源是否与index.html您正在使用文件位于同一目录中,CORS 都将适用对我来说,这意味着当我将它上传到我的服务器时 CORS 问题消失了,因为它有一个域。

这是正确的,因为我有同样的问题。我正在使用 phpstorm 查看它,它使用一个模拟服务器本身并且可以工作。
2021-05-04 19:06:24
我通过python -m http.server port 8080在我的工作文件夹中使用本地工作,然后访问http://localhost:8080.
2021-05-08 19:06:24
对于 PHP,您可以使用 php --server localhost:8080
2021-05-13 19:06:24
@Noumenon,python 服务器提示 +1
2021-05-13 19:06:24

您可以在画布上使用图像的 base64,在转换为 base64 时,您可以在图像路径之前使用代理 URL ( https://cors-anywhere.herokuapp.com/ ) 以避免跨域问题

在此处查看完整详细信息

https://stackoverflow.com/a/44199382/5172571

var getDataUri = function (targetUrl, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        var reader = new FileReader();
        reader.onloadend = function () {
            callback(reader.result);
        };
        reader.readAsDataURL(xhr.response);
    };
    var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    xhr.open('GET', proxyUrl + targetUrl);
    xhr.responseType = 'blob';
    xhr.send();
};
getDataUri(path, function (base64) {
    // base64 availlable here
})