canvas.toDataURL ()에서 보안 예외가 발생하는 이유는 무엇입니까?


90

충분한 수면을 취하지 않았습니까? 이 다음 코드

var frame=document.getElementById("viewer");
frame.width=100;
frame.height=100;

var ctx=frame.getContext("2d");
var img=new Image();
img.src="http://www.ansearch.com/images/interface/item/small/image.png"

img.onload=function() {
    // draw image
    ctx.drawImage(img, 0, 0)

    // Here's where the error happens:
    window.open(frame.toDataURL("image/png"));
}

이 오류가 발생합니다.

SECURITY_ERR: DOM Exception 18

이것이 작동하지 않을 방법이 없습니다! 누구든지 이것을 설명 할 수 있습니까?



2
이 솔루션은 Adobe AIR를 사용하지 않는 사람들에게는 유용하지 않은 것 같습니다.
ObscureRobot 2013-08-16

답변:


68

에서 사양 은 말합니다 :

origin-clean 플래그가 false로 설정된 캔버스 요소의 toDataURL () 메서드가 호출 될 때마다 메서드는 SECURITY_ERR 예외를 발생시켜야합니다.

이미지가 다른 서버에서 오는 경우 toDataURL ()을 사용할 수 없다고 생각합니다.


6
공격자가 개인 사이트에있는 사진의 이름을 추측 할 수있는 경우 캔버스에 그림을 그리고 새 이미지를 자신의 사이트로 전송하여 사진의 복사본을 얻을 수 있습니다. 내 관점에서 볼 때 주요 제한은 다른 사이트의 콘텐츠를 그리는 것을 피하는 것이지만 공격자가 예기치 않은 사이트에서 구멍을 찾을 수 있으므로 보안이 너무 복잡합니다.
AlfonsoML 2010 년

3
하위 도메인도 중요합니다. 내 경험상 Chrome에서 하위 도메인에 걸쳐있는 것으로 인식되는 호출을 할 때 최소한 SECURITY_ERR : DOM Exception 18이 발생합니다. 1. foo의 동영상 또는 이미지에 대한 example.com/some/path/index.html .example.com 2. 1과 동일한 페이지로 이동하지만 URL example.com/some/path/index.html 을 입력 한 다음 www.example.com의 동영상 또는 이미지에 대해 toDataUrl () 호출을 시도하는 경우
Sam Dutton 2010-06-25

3
@AlfonsoML, 내가 틀렸을 수도 있지만 "공격자가 개인 사이트에있는 사진의 이름을 추측 할 수 있다면"브라우저를 사용하여 이미지를 컬 비로 잡을 것입니다. 내 관점 : 공개 URL 공개 콘텐츠.
kilianc

4
@ pop850 데이터 URL을 사용하는 경우에도이 문제가 발생합니다. 데이터 URL에 대해이 문제를 해결할 수있는 방법이 있습니까?
Sujay

6
@kilianc이 제한은 공격자가 귀하의 브라우저 (인증 쿠키 포함)가 이미지를 가져 와서 그 내용을 공격자에게 보내도록하는 것을 방지하기 위해 존재합니다 . 공격자는 귀하의 쿠키를 가지고 있지 않으므로 귀하가받을 권한이있는 동일한 리소스를 얻기 위해 curl을 사용할 수 없습니다. "공개 URL, 공개 콘텐츠"는 다소 결함이있는 사고 방식입니다. 내 Facebook 페이지에는 공개 구성 요소가 있지만 올바른 인증 토큰으로 만 액세스 할 수있는 것이 많습니다.
apsillers

18

이미지 객체에 대한 교차 출처 속성 설정이 저에게 효과적이었습니다 (나는 fabricjs를 사용했습니다)

    var c = document.createElement("img");
    c.onload=function(){
        // add the image to canvas or whatnot
        c=c.onload=null
    };
    c.setAttribute('crossOrigin','anonymous');
    c.src='http://google.com/cat.png';

fabricjs를 사용하는 경우 Image.fromUrl을 패치하는 방법은 다음과 같습니다.

// patch fabric for cross domain image jazz
fabric.Image.fromURL=function(d,f,e){
    var c=fabric.document.createElement("img");
    c.onload=function(){
        if(f){f(new fabric.Image(c,e))}
        c=c.onload=null
    };
    c.setAttribute('crossOrigin','anonymous');
    c.src=d;
};

감사합니다. Chrome에서 작동합니다. 그래도 난 fabric.js를 사용하고 있지 않다
Philip007

fabricjs를 사용하지만 해결할 수 없습니다. 이 코드로 어떻게할까요? function wtd_load_bg_image (img_url) {if (img_url) {var bg_img = new Image (); bg_img.onload = function () {canvasObj.setBackgroundImage (bg_img.src, canvasObj.renderAll.bind (canvasObj), {originX : 'left', originY : 'top', left : 0, top : 0}); }; bg_img.src = img_url; }}
HOY

Firefox에서도 작동합니다.
vanowm

16

이미지가 Access-Control-Allow-Origin 또는 Access-Control-Allow-Credentials 중 하나를 설정하는 호스트에서 호스팅되는 경우 CORS (Cross Origin Resource Sharing)를 사용할 수 있습니다. 자세한 내용은 여기 (crossorigin 속성)를 참조하십시오.

다른 옵션은 서버에 이미지를 가져 와서 제공하는 엔드 포인트를 갖는 것입니다. (예 : http : // your_host / endpoint? url = URL ) 이러한 접근 방식의 단점은 지연 시간과 이론적으로 불필요한 가져 오기입니다.

대체 솔루션이 더 있다면 그에 대해 듣고 싶습니다.


안녕하세요, 저는 Access-Control-Allow-Origin이 있습니다. * 이미지에 crossorigin = 'anonymous'가 있고 캔버스에 이미지를 그린 다음 toDataUrl을 호출하고 여전히 SECURITY_ERR을 얻습니다. : DOM 예외 18
skrat

13

이미지 호스팅이 이미지 리소스에 대해 다음 HTTP 헤더를 제공 할 수 있고 브라우저가 CORS를 지원하는 경우이를 방지하는 방법이있는 것 같습니다.

액세스 제어 허용 출처 : *
액세스 제어 허용 자격 증명 : true

http://www.w3.org/TR/cors/#use-cases에 명시되어 있습니다.


1
access-control-allow-credentials : true는 access-control-allow-origin : *에서 작동하지 않습니다. 전자가 설정되면, 후자는 원점 값이 아니라에서 와일드 카드 값이 있어야 developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
실버 곤잘레스

4

마침내 해결책을 찾았습니다. func에 crossOrigin세 번째 매개 변수를 추가하면 됩니다.fromURL

fabric.Image.fromURL(imageUrl, function (image) {
            //your logic
    }, { crossOrigin: "Anonymous" });

2

나는 동일한 문제가 있었고 모든 이미지가 동일한 도메인에서 호스팅됩니다 ... 따라서 누군가가 동일한 문제를 겪고 있다면 여기에 내가 해결 한 방법이 있습니다.

하나는 캔버스를 생성하고 다른 하나는 캔버스에서 이미지를 생성하는 두 개의 버튼이 있습니다. 그것은 나에게만 효과가 있었으며 첫 번째 버튼에 모든 코드를 작성했을 때 이유를 모르겠다는 점에 유감입니다. 그래서 클릭하면 캔버스와 이미지가 동시에 생성됩니다.

코드가 다른 기능에있을 때 항상이 보안 문제가 있습니다 ... = /


2

나는 이것을 사용하여 작동시킬 수 있었다.

.htaccess소스 서버 의 첫 번째 줄에 작성하십시오.

Header add Access-Control-Allow-Origin "*"

그런 다음 <img>요소를 만들 때 다음과 같이하십시오.

// jQuery
var img = $('<img src="http://your_server/img.png" crossOrigin="anonymous">')[0]

// or pure
var img = document.createElement('img');
img.src='http://your_server/img.png';
img.setAttribute('crossOrigin','anonymous');

1

ID에 공백을 넣을 수 없습니다.

최신 정보

내 생각 엔 이미지가 스크립트를 실행하는 것과 다른 서버에 있다는 것입니다. 내 페이지에서 실행할 때 오류를 복제 할 수 있었지만 동일한 도메인에서 호스팅되는 이미지를 사용하는 순간 제대로 작동했습니다. 따라서 보안과 관련이 있습니다. 이미지를 귀하의 사이트에 올리십시오. 왜 이것이 사실인지 아는 사람이 있습니까?


0

캔버스에 이미지를 단순히 그리는 경우 동일한 도메인에서 이미지를로드하고 있는지 확인하십시오.

www.example.comexample.com 과 다릅니다.

따라서 주소 표시 줄에있는 이미지와 URL이 www이든 아니든 동일한 지 확인하십시오.


0

fabric.js를 사용하고 있으며 toDataURL 대신 toDatalessJSON을 사용하여이 문제를 해결할 수 있습니다.

canvas.toDatalessJSON({ format: 'jpeg' }).objects[0].src

편집 : 신경 쓰지 마세요. 이로 인해 배경 이미지 만 JPG로 내보내지고 맨 위에 그림이 표시되지 않아 결국 완전히 유용하지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.