【问题标题】:HTML crossorigin attribute for img tagimg 标签的 HTML 跨域属性
【发布时间】:2014-11-11 22:19:46
【问题描述】:

我正在尝试了解如何为 img 标签使用 crossorigin 属性。我找不到一个很好的例子(我发现的关于启用 CORS 的图像是用 JavaScript 代码解释的,因此我看不到带有 img 标签的 crossorigin 属性。

我有一个猜测,如果我理解错误,请纠正我的错误。

首先可以编写下面的代码段来将图像绘制到画布上:

<canvas id="canvas" width=400 height=400></canvas>
<br><br>
<img id="image" src="http://...." alt="" width="400" height="400">
<script>
function draw() {
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var img = new Image();
    img.crossOrigin = "Anonymous";
    img.src = document.getElementById("image").value;
    context.drawImage(img, 40, 40);
}
</script>

下面的代码是否等同于上面的代码?它不包含“img.crossOrigin”,但在 img 标签中有 crossorigin 属性。

<canvas id="canvas" width=400 height=400></canvas>
<br><br>
<img id="image" crossorigin="anonymous"src="http://...." alt="" width="400" height="400">
<script>
function draw() {
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var img = new Image();
    img.src = document.getElementById("image").value;
    context.drawImage(img, 40, 40);
}
</script>

说实话,我无法进行实验,因为我不知道哪个网站允许将其图像用作 CORS。

我的猜测是,如果一个站点允许在 CORS 请求由匿名完成的情况下在画布中使用其图像,您可以在画布中绘制它,如果不是,即使请求是由匿名完成的,您也无法在画布中绘制它(我不确定我是否在这里)。因此,上述两个示例都必须匿名请求 CORS。

你能说如果他们两个工作相同吗?如果不是,请您解释一下原因并举个例子,使用带有 img 标签的 crossorigin 属性?

【问题讨论】:

    标签: html canvas cors


    【解决方案1】:

    由于您使用#image 元素作为图像的来源,因此您的代码的两个版本大致相同。

    但是...

    img 元素中没有crossorigin="anonymous" 的版本可能仍然会产生跨域冲突。

    这是因为图像最初加载到 img 元素中没有将跨域标志设置为匿名

    javascript 代码可能会使用来自 img 元素的图像的缓存版本,而不是尝试从 http://...重新加载它。

    这意味着缓存的图像数据仍会将画布污染为包含跨域内容。

    顺便说一句,您的代码中有语法错误:

    // Not:  img.src = document.getElementById("image").value;
    
    img.src = document.getElementById("image").src;
    

    【讨论】:

    • 非常感谢您的解释。据我了解,没有'crossorigin =“anonymous”'的图像可能不会被绘制到画布上,因为它会被污染。但是我尝试了一个没有 'crossorigin="anonymous"' 和 'img.crossOrigin = "Anonymous";' 的版本,它在 Chrome 中工作。怎么会这样?如果没有 CROS 请求,图像不应该被污染吗?
    • 更正:我尝试不使用 img 元素作为源。很抱歉造成混乱。
    • 使用不同的浏览器版本会得到不同的结果。这是因为浏览器目前正在努力解决如何让编码人员进行跨域请求,同时保护用户免受跨域黑客攻击(例如使用画布窃取银行登录屏幕的快照)。如果您不需要 img 元素,请使用 javascript 代码使用 cross-origin=anonymous 直接下载图像。此外,请确保您的图像服务器正在添加适当的 X-origin 标头。顺便说一句,drawImage 将始终有效,但如果画布被污染,其他命令(.toDataURL 和 .getImageData)将失败。
    • 感谢您的信息。为什么drawImages总是有效?如果画布被污染,它们试图从图像接收数据,其他命令的共同点是否会失败?
    • drawImage 始终有效,因为它正在写入画布。恶意代码尝试使用 .toDataURL 和 .getImageData 等画布方法进行读取。所以:写==安全,读==你的银行账户现在是空的。 ;-)