DOM安全异常18:污染的画布 [英] DOM Security Exception 18: Tainted Canvas

查看:98
本文介绍了DOM安全异常18:污染的画布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我几乎完成了一个基于Javascript / HTML5的游戏,我已经通过使用Chrome来打开本地文件系统上的HTML页面(我还没有在任何地方上传任何东西)来测试。我正在使用Chrome的文件:// 协议来执行此操作。但我遇到了一个问题...在游戏开始的时候,我显示一个图像几秒钟,然后移动到菜单屏幕上。我通过抓住画布的像素数据来暂停游戏,显示,然后在整个事物上绘制一个半透明的矩形,并以十字准线作为自定义指针。但是,Chrome让我担心DOM安全异常18:无法从画布中获取图像数据,因为画布已经被跨原始数据所污染。



所以我在互联网上做了一些研究,事实证明,这是因为Chrome看到图像被从本地文件系统中抓取,并将其视为一个安全错误。我使用这个问题作为参考,我尝试了对Cross-Origin的一些研究资源共享,但很快就迷路了。我认为使用 http:// localhost 简单打开测试HTML文件会更容易回答者建议。但是我也不知道如何做到这一点。



我真的很想使用Chrome来继续测试我的游戏(开发者工具通过 Ctrl-Shift-I 已经证明是非常宝贵的),所以我想到有三个解决方案:要么弄清楚CORS是什么以及如何使用它,要学习如何使用 http:// ,或以某种方式将我的图像数据硬编码为JavaScript脚本文件中的变量(如C中的XPM文件)。我不知道如何做前两个,我想避免第三个。

解决方案

是的,这是可能是下载本地Web服务器或注册托管服务器的时间。



但是,如果您想在没有服务器的情况下继续测试,则可以注册一个免费的保管箱.com帐号并托管您的图像。



Dropbox允许使用CORS友好的crossOrigin =anonymous访问图像。



然后CORS在Chrome& Mozilla的。但是,IE仍然无法CORS友好 - 来自IE:(



以下是如何从dropbox(Chrome和Mozilla,而不是IE)加载没有CORS问题的图像。



在设置image.src之前,secret设置为image.crossOrigin =anonymous:

  var externalImage2 = document.createElement(img); 
externalImage2.onload = function(){
canvas.width = externalImage2.width;
canvas.height = externalImage2.height;
ctx.drawImage(externalImage2,0,0);
//使用getImageData替换为黄色的蓝色
var imageData = recolorImage(externalImage2,0,0,255,255,255 ,0);
//将更改的数据放回画布上
//这将导致CORS违规的失败
ctxAnonymous.putImageData(imageData,0,0);
}
externalImage2.crossOrigin =Anonymous;
externalImage2.src =https://dl.dropboxusercontent.com/u/139992952/stack上溢/ colorhouse.png;

这里是代码和小提琴: http://jsfiddle.net/m1erickson/YdzHT/

  <!doctype html> 
< html>
< head>
< link rel =stylesheettype =text / cssmedia =allhref =css / reset.css/> <! - reset css - >
< script type =text / javascriptsrc =http://code.jquery.com/jquery.min.js>< / script>

< style>
body {background-color:ivory; }
画布{border:1px solid red;}
< / style>

< script>
$(function(){

var canvas = document.getElementById(canvas);
var ctx = canvas.getContext(2d);
var canvasCORS = document.getElementById(canvasCORS);
var ctxCORS = canvasCORS.getContext(2d);
var canvasAnonymous = document.getElementById(canvasAnonymous);
var ctxAnonymous = canvasAnonymous.getContext(2d);

//使用图像WITHOUT crossOrigin = anonymous
//在所有浏览器中失败
var externalImage1 = new Image();
externalImage1.onload = function(){
canvas.width = externalImage1.width;
canvas.height = externalImage1.height;
ctx.drawImage(externalImage1,0,0);
//使用getImageData用黄色代替蓝色
var imageData = recolorImage(externalImage1,0,0,255,255,255,0);
//将更改的数据放回画布上
//这将导致CORS违规的失败
ctxCORS.putImageData(imageData,0,0);
}
externalImage1.src =https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png;

//使用图像WITH crossOrigin = anonymous
//成功在Chrome + Mozilla,仍然失败IE
var externalImage2 = new Image();
externalImage2.onload = function(){
canvas.width = externalImage2.width;
canvas.height = externalImage2.height;
ctx.drawImage(externalImage2,0,0);
//使用getImageData用黄色代替蓝色
var imageData = recolorImage(externalImage2,0,0,255,255,255,0);
//将更改的数据放回画布上
//这将导致CORS违规的失败
ctxAnonymous.putImageData(imageData,0,0);
}
externalImage2.crossOrigin =匿名;
externalImage2.src =https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png;


函数recolorImage(img,oldRed,oldGreen,oldBlue,newRed,newGreen,newBlue){
var c = document.createElement('canvas');
var ctx = c.getContext(2d);
var w = img.width;
var h = img.height;
c.width = w;
c.height = h;

//在临时画布上绘制图像
ctx.drawImage(img,0,0,w,h);

//将整个图像拉入像素数据数组
var imageData = ctx.getImageData(0,0,w,h);

//检查每个像素,
//将任何旧的rgb更改为新的rgb
(var i = 0; i< imageData.data.length; i + = 4)
{
//这个像素是旧的rgb吗?
if(imageData.data [i] == oldRed&&
imageData.data [i + 1] == oldGreen&&
imageData.data [i + 2] == oldBlue
){
//更改为新的rgb
imageData.data [i] = newRed;
imageData.data [i + 1] = newGreen;
imageData.data [i + 2] = newBlue;
}
}
return(imageData);
}


}); // end $(function(){});
< / script>

< / head>

< body>
< p>原始外部图像< / p>
< canvas id =canvaswidth = 140 height = 140>< / canvas>
< p> .getImageData with .crossOrigin ='anonymous'
< p> [在Chrome + Mozilla中成功仍然在IE中失败]< / p>
< canvas id =canvasAnonymouswidth = 140 height = 140>< / canvas>
< p> .getImageData没有.crossOrigin ='anonymous'
< p> [在所有浏览器上失败]< / p>
< canvas id =canvasCORSwidth = 140 height = 140>< / canvas>
< / body>
< / html>


I'm nearly finished with a Javascript/HTML5-based game, and i've been testing it by using Chrome to open the HTML page on my local file system (i haven't uploaded anything anywhere). I'm using Chrome's file:// protocol to do this. But i'm running into a problem... At the beginning of the game, i display an image for a couple seconds before moving onto the menu screen. I pause the game by grabbing the canvas' pixel data, displaying that, then drawing a semi-transparent rectangle across the whole thing, with a crosshair as a custom pointer. However, Chrome is giving me trouble about a DOM Security Exception 18: "Unable to get image data from canvas because the canvas has been tainted by cross-origin data."

So i did some research on the Internet, and it turns out this is because Chrome sees that the image is grabbed from the local file system, and sees this as a security error. Using this question as a reference, i tried doing some research on Cross-Origin Resource Sharing, but quickly got lost. I figured it would be much easier to simply open the test HTML file using http:// and localhost like the question answerer suggested. But i have no idea how to do this, either.

I'd really like to use Chrome to continue testing my game (the developer tools accessed through Ctrl-Shift-I have proved to be invaluable), so i figured there were three solutions: Either figure out what CORS is and how to use it, learn how to open a local file using http://, or somehow hard-code my image data as a variable in my JavaScript script file (like a XPM file in C). I don't know how to do the first two, and i'm trying to avoid the third.

解决方案

Yes, it’s probably time to download a local web server or sign up for a hosted server.

But if you want to continue testing without a server, you can sign up for a free dropbox.com account and host your images there.

Dropbox allows access to images using CORS friendly crossOrigin="anonymous".

Then CORS is no problem on Chrome & Mozilla. But, IE still fails to be CORS friendly—come on IE :(

Here’s how to load an image without CORS problems from dropbox (Chrome & Mozilla, not IE).

The "secret" is setting image.crossOrigin="anonymous" before setting the image.src:

    var externalImage2=document.createElement("img");
    externalImage2.onload=function(){
        canvas.width=externalImage2.width;
        canvas.height=externalImage2.height;
        ctx.drawImage(externalImage2,0,0);
        // use getImageData to replace blue with yellow
        var imageData=recolorImage(externalImage2,0,0,255,255,255,0);
        // put the altered data back on the canvas  
        // this will FAIL on a CORS violation
        ctxAnonymous.putImageData(imageData,0,0);    
    }
    externalImage2.crossOrigin = "Anonymous";
    externalImage2.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/YdzHT/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var canvasCORS=document.getElementById("canvasCORS");
    var ctxCORS=canvasCORS.getContext("2d");
    var canvasAnonymous=document.getElementById("canvasAnonymous");
    var ctxAnonymous=canvasAnonymous.getContext("2d");

    // Using image WITHOUT crossOrigin=anonymous
    // Fails in all browsers
    var externalImage1=new Image();
    externalImage1.onload=function(){
        canvas.width=externalImage1.width;
        canvas.height=externalImage1.height;
        ctx.drawImage(externalImage1,0,0);
        // use getImageData to replace blue with yellow
        var imageData=recolorImage(externalImage1,0,0,255,255,255,0);
        // put the altered data back on the canvas  
        // this will FAIL on a CORS violation
        ctxCORS.putImageData(imageData,0,0);    
    }
    externalImage1.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";

    // Using image WITH crossOrigin=anonymous
    // Succeeds in Chrome+Mozilla, Still fails in IE
    var externalImage2=new Image();
    externalImage2.onload=function(){
        canvas.width=externalImage2.width;
        canvas.height=externalImage2.height;
        ctx.drawImage(externalImage2,0,0);
        // use getImageData to replace blue with yellow
        var imageData=recolorImage(externalImage2,0,0,255,255,255,0);
        // put the altered data back on the canvas  
        // this will FAIL on a CORS violation
        ctxAnonymous.putImageData(imageData,0,0);    
    }
    externalImage2.crossOrigin = "Anonymous";
    externalImage2.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/colorhouse.png";


    function recolorImage(img,oldRed,oldGreen,oldBlue,newRed,newGreen,newBlue){
        var c = document.createElement('canvas');
        var ctx=c.getContext("2d");
        var w = img.width;
        var h = img.height;
        c.width = w;
        c.height = h;

        // draw the image on the temporary canvas
        ctx.drawImage(img, 0, 0, w, h);

        // pull the entire image into an array of pixel data
        var imageData = ctx.getImageData(0, 0, w, h);

        // examine every pixel, 
        // change any old rgb to the new-rgb
        for (var i=0;i<imageData.data.length;i+=4)
          {
              // is this pixel the old rgb?
              if(imageData.data[i]==oldRed &&
                 imageData.data[i+1]==oldGreen &&
                 imageData.data[i+2]==oldBlue
              ){
                  // change to your new rgb
                  imageData.data[i]=newRed;
                  imageData.data[i+1]=newGreen;
                  imageData.data[i+2]=newBlue;
              }
          }
        return(imageData);
    }


}); // end $(function(){});
</script>

</head>

<body>
    <p>Original external image</p>
    <canvas id="canvas" width=140 height=140></canvas>
    <p>.getImageData with .crossOrigin='anonymous'
    <p>[Succeeds in Chrome+Mozilla, still fails in IE]</p>
    <canvas id="canvasAnonymous" width=140 height=140></canvas>
    <p>.getImageData without .crossOrigin='anonymous'
    <p>[Fails on all browsers]</p>
    <canvas id="canvasCORS" width=140 height=140></canvas>
</body>
</html>

这篇关于DOM安全异常18:污染的画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆