【问题标题】:Tainted Canvas, due to CORS and SVG?受污染的画布,由于 CORS 和 SVG?
【发布时间】:2014-10-07 19:59:53
【问题描述】:

我知道这个问题以前经常被问到,但是在尝试解决这个问题 3 天后,我显然需要帮助。

我的问题已经有一段时间了。我一直在尝试做这样的事情(这是一个简化的代码):

var media = Array();
$(document).ready(function(){
img = new Image();
img.crossOrigin = "*";
img.src = "http://domain.com/pics/picture.svg";
img.width = 200;
img.height = 300;
img.onload = function(){

    media['test'] = img;

    ///var layer = img;
    $.jCanvas({
        fromCenter: false
    });

    $("#collider").drawImage({
        source: media['test'],
        width: 200,
        height: 300,
        x: 0, y: 0,
        click: function(layer){
            alert(layer.eventX);
        }
    });


    var pixelData = document.getElementById("collider").getContext('2d').getImageData(50, 50, 20, 20).data;
    console.log(pixelData);//*/
}

});

问题是画布被污染了。因此,我无法获得任何像素数据。

我尝试在 .htaccess 中使用以下代码设置访问控制原始标头:

# with AJAX withCredentials=false (cookies NOT sent)
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, PUT, OPTIONS, PATCH, DELETE"
Header always set Access-Control-Allow-Headers "X-Accept-Charset,X-Accept,Content-Type"

# with AJAX withCredentials=true (cookies sent, SSL allowed...)
SetEnvIfNoCase ORIGIN (.*) ORIGIN=$1
Header always set Access-Control-Allow-Methods "POST, GET, PUT, OPTIONS, PATCH, DELETE"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Allow-Headers "X-Accept-Charset,X-Accept,Content-Type"

当我在浏览图像 URL 时检查浏览器中的标题时,它们似乎正在工作(所有标题都按应有的方式发送)。但是当它们以某种方式通过 javascript 加载时,它们不会(在浏览器中检查时根本不发送标头),因此画布被污染了

我的问题: 1) 为什么我的 .htaccess 文件不允许跨组织共享数据? 2) 为什么我的 html、javascript 和图像文件都托管在同一个域上,所以我什至会遇到跨域数据问题?

附加信息: 服务器:Ubuntu LTS 12.04、Apache2

编辑 我试图将 picture.svg 更改为 .jpg 图片,现在一切正常,所以显然问题似乎来自包含的 .svg 文件。

有谁知道如何处理 .svg 文件?

【问题讨论】:

  • 通过一些搜索找到了这个,也许它有助于回答你的一些问题:stackoverflow.com/questions/5495952/…。如果所有内容都是从“domain.com”加载的,那么根本不存在跨域问题。如果有什么不同,例如http vs https,或者不同的端口,那么你在不同的域中。
  • 我的代码可以很好地打印图片,所以这不是问题。一切都是使用http从“domain.com”加载的,所以我不明白为什么这是一个跨域问题...
  • 如果是我,我会减少问题 - 禁用 CORS,因为正如您所说,您不需要它。您还没有真正解释为什么首先添加 CORS...
  • 因为报错提示canvas被跨域数据污染
  • 啊,大概你的svg正在加载跨域资源,例如:otherdomain.com/image.svg"></svg>

标签: javascript apache canvas cors jcanvas


【解决方案1】:

更新

错过了您使用的是 SVG 文件。如果 SVG 文件包含对外部源(CSS、对象、图像等)的任何引用,它将不起作用。 SVG 中的所有内容都必须内联。否则您将遇到与直接使用外部资源相同的情况,但由于它们被封装在 SVG 中,因此浏览器更加严格,因此在这些情况下您不能使用 CORS。

这是浏览器的一项安全功能,您无法对其进行太多更改,但要确保嵌入 SVG 所需的所有资源。

【讨论】:

  • 我已经尝试了您的建议,但出现了同样的错误。它不是本地主机。而且我没有使用任何特殊的端口号(标准 80 除外)
  • @PhilipG 我想念你在哪里使用 SVG 作为图像,请查看更新的答案。
  • 这是讨论 CORS + SVG 的 Chromium 问题:code.google.com/p/chromium/issues/detail?id=470601
【解决方案2】:

正如所指出的。 SVG 图像会污染画布。甚至在 SVG 文件没有外部资源的时候(比如我的情况)。

但我找到了一种解决方案,因此仍然可以使用 SVG 格式的功能而不会污染画布。

canvg (http://code.google.com/p/canvg/) 可以。该脚本还声称能够使用 CORS 获取 SVG(虽然我还没有测试过)

希望这对某人有所帮助!

代码示例

//...prev code
canvg(document.getElementById('collider'), media['test']);

var pixelData = document.getElementById("collider").getContext('2d').getImageData(50, 50, 20, 20).data;
console.log(pixelData);

【讨论】:

  • 请注意,&lt;img&gt; 中的 SVG 根本无法拥有任何外部资源。因此,除非 svg 文件本身是从跨域资源提供的,否则您不会违反同源策略。浏览器试图通过在画布上绘制 svg 来污染画布来保护您的隐私。 SVG 可能会泄露一些通常无法访问的系统信息。 (例如访问过的链接、一些浏览器的皮肤等)
猜你喜欢
  • 2017-12-18
  • 2017-12-05
  • 2013-02-07
  • 2014-04-18
  • 1970-01-01
  • 2014-05-07
  • 2018-02-11
相关资源
最近更新 更多