Javascript 画布被跨源数据污染

Javascript 画布被跨源数据污染,javascript,canvas,cross-domain,cors,mjpeg,Javascript,Canvas,Cross Domain,Cors,Mjpeg,我正在从第三方网站加载一个我可以信任的运动jpeg。我试图getImageData(),但浏览器(Chrome 23.0)抱怨: Unable to get image data from canvas because the canvas has been tainted by cross-origin data. 还有一些类似的问题,但他们使用的是本地文件,我使用的是第三方媒体。我的脚本在共享服务器上运行,而我不拥有远程服务器 我尝试了img.crossOrigin='Anonymous'

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

Unable to get image data from canvas because the canvas has been tainted by
cross-origin data.
还有一些类似的问题,但他们使用的是本地文件,我使用的是第三方媒体。我的脚本在共享服务器上运行,而我不拥有远程服务器


我尝试了
img.crossOrigin='Anonymous'
img.crossOrigin='
(请参阅),但没有任何帮助。您知道如何在具有跨源数据的画布上
getImageData
吗?谢谢

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


但是不可以,您不能也不应该使用来自不支持CORS的外部源的getImageData()。另外值得注意的是,如果您在本地工作,则CORS将适用,无论该资源是否与您正在使用的
index.html
文件位于同一目录中。对我来说,这意味着当我将CORS问题上传到我的服务器时,它就消失了,因为它有一个域。

虽然这个问题已经很老了,但问题仍然存在,网络上几乎没有什么可以解决的。我提出了一个解决方案,希望与大家分享:

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

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

HTML:

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

2014年1月更新:

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


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

您可以使用画布上图像的base64, 转换为base64时,可以在映像路径之前使用代理URL(),以避免跨源问题

在此处查看全部详细信息


谢谢你的回复。不确定我们是否可以将
toDataURL()
应用于mjpeg,但我会尝试一下。为什么不?安全原因?是否有外部服务器应该做的特定配置?即使他们没有这样的配置,我也可以使用toDataURL来实现。是的,这是一个很大的安全问题。这能和CORS一起工作吗?我在这方面还没有成功。我怎么知道呢?假设你有一个
标签,但你不知道它是什么。。。您如何知道您是否可以绘制它,或者是否需要使用
crossorigin=“anonymous”
加载它?@TomášZato您不知道,因为这正是CORS试图阻止的。只有在您事先知道图像是什么以及图像是否安全的情况下,才允许使用。谢谢您的回复。那么,对于“工作”,您的意思是可以在这个外部资源上执行
getImageData
?如果我们像你提到的那样解决问题。旧答案,但要注意另一种方法似乎更简单:首先设置img标记的交叉原点,听它的
错误
事件处理程序,设置远程src,如果它触发,你知道你会污染画布。也许你信任那个第三方网站,但用户无法判断第三方网站是否信任您。您的脚本可以从第三方网站提取图像,该网站仅可供用户访问,而您无法访问(可能是因为它仅可供注册用户使用,并且用户已登录)。然后脚本可以将该图像数据转发到您自己的服务器,并允许您非法访问。这是正确的,因为我也有同样的问题。我正在使用phpstorm来查看它,它使用一个模拟服务器本身并工作。我在本地工作,在我的工作文件夹中使用
python-mhttp.server端口8080
,然后访问
http://localhost:8080
。对于PHP,您可以使用PHP--server localhost:8080
@Noumenon,+1作为python服务器提示
<img id="testImage" src="path/to/image.png?_t=1234">
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 */
});
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"
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
})