getImageData () 오류 수정 방법 교차 출처 데이터로 인해 캔버스가 오염 되었습니까?


131

내 코드는 로컬 호스트에서 잘 작동하지만 사이트에서는 작동하지 않습니다.

이 줄에 대해 콘솔 에서이 오류가 발생했습니다 .getImageData(x,y,1,1).data.

Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 

내 코드의 일부 :

jQuery.Event.prototype.rgb=function(){
        var x =  this.offsetX || (this.pageX - $(this.target).offset().left),y =  this.offsetY || (this.pageY - $(this.target).offset().top);
        if (this.target.nodeName!=="CANVAS")return null;
        return this.target.getContext('2d').getImageData(x,y,1,1).data;
    }

참고 : 내 이미지 URL (src)은 하위 도메인 URL에서 온 것입니다.


8
img.src가 로컬 상대 URL 인 "img / foo.png"인 경우에도이 오류가 발생합니다.이 문제에 대한 교차 출처는 무엇입니까?
Sanford Staab

참조 stackoverflow.com/a/16218015/5175433를 : "크롬은 다른 로컬 파일을 고려하지 않고 동일한 도메인에서 공급합니다."
A_P

답변:


116

다른 사람들이 말했듯이 크로스 원점 도메인에서로드하여 캔버스를 "오염"하고 있습니다.

https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image

그러나 다음을 간단히 설정하여이를 방지 할 수 있습니다.

img.crossOrigin = "Anonymous";

이것은 원격 서버가 다음 헤더를 적절하게 설정 한 경우에만 작동합니다.

Access-Control-Allow-Origin "*"

"직접 링크"옵션을 사용할 때 의 Dropbox 파일 선택기 는 이에 대한 좋은 예입니다. 나는 oddprints.com 에서 그것을 사용 하여 원격 dropbox 이미지 URL에서 캔버스로 이미지 를 가져간 다음 이미지 데이터를 다시 서버로 제출합니다. 자바 스크립트의 모든


1
jsfiddle.net 내로 imgur 이미지를로드 할 때이 오류를 해결하기 위해 노력
트래비스 J를

3
crossorigin을 먼저 넣은 다음 소스를 설정 한 다음 데이터 onload에 액세스하면 나를 위해 일했습니다
jones

2
로컬 파일이고 앱이 인터넷을 전혀 사용하지 않으면 어떻게 되나요? 안드로이드 웹뷰 앱처럼 이미지는 html 파일과 같은 폴더에 있습니다. 이것은 해결되지 않습니다.
커티스

44

헤더 .setAttribute('crossOrigin', '')가없는 304 응답을 피하기 위해 URL 쿼리 문자열에 타임 스탬프 를 사용해야 하고 타임 스탬프를 추가 해야한다는 것을 알았습니다 Access-Control-Allow-Origin.

이것은 나를 준다

var url = 'http://lorempixel.com/g/400/200/';
var imgObj = new Image();
imgObj.src = url + '?' + new Date().getTime();
imgObj.setAttribute('crossOrigin', '');

3
로컬 파일에 서버 없이이 작업을 시도하면 다음과 같은 결과가 나타납니다. . 따라서 원점 '널'은 액세스가 허용되지 않습니다.
Sanford Staab

1
단순히 imgObj.setAttribute('crossOrigin', '')나를 사용하여 해결했습니다-감사합니다! 여기img.crossOrigin = "Anonymous" 에서도 언급했듯이 작동합니다 . @SanfordStaab 브라우저는 로컬 파일을 다른 도메인에있는 것으로 취급합니다. 그렇지 않으면 웹 사이트 소유자가 로컬 파일을 읽을 수 있습니다. 동일한 도메인에서 이미지를 요청하거나 요청에 대한 응답으로 헤더에 다른 도메인의 코드가 해당 파일을 읽을 수 있음을 브라우저에 알려야합니다.

19

다른 서버에서 직접 캔버스로 이미지를 그린 다음을 사용할 수 없습니다 getImageData. 보안 문제이며 캔버스는 "오염 된"것으로 간주됩니다.

PHP를 사용하여 이미지 사본을 서버에 저장 한 다음 새 이미지를로드하는 것이 효과가 있습니까? 예를 들어, URL을 PHP 스크립트로 전송하여 서버에 저장 한 후 다음과 같이 새 파일 이름을 자바 스크립트로 반환 할 수 있습니다.

<?php //The name of this file in this example is imgdata.php

  $url=$_GET['url'];

  // prevent hackers from uploading PHP scripts and pwning your system
  if(!@is_array(getimagesize($url))){
    echo "path/to/placeholderImage.png";
    exit("wrong file type.");
  }

  $img = file_get_contents($url);

  $fn = substr(strrchr($url, "/"), 1);
  file_put_contents($fn,$img);
  echo $fn;

?>

PHP 스크립트를 다음과 같은 ajax javascript와 함께 사용하십시오.

xi=new XMLHttpRequest();
xi.open("GET","imgdata.php?url="+yourImageURL,true);
xi.send();

xi.onreadystatechange=function() {
  if(xi.readyState==4 && xi.status==200) {
    img=new Image;
    img.onload=function(){ 
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    }
    img.src=xi.responseText;
  }
}

getImageData그 후에 캔버스에서 사용 하면 제대로 작동합니다.

또는 전체 이미지를 저장하지 않으려면 x & y 좌표를 PHP 스크립트에 전달하고 해당면의 픽셀 rgba 값을 계산할 수 있습니다. PHP에서 이러한 종류의 이미지 처리를 수행하기위한 좋은 라이브러리가 있다고 생각합니다.

이 방법을 사용하려면 구현에 도움이 필요하면 알려주십시오.

편집-1 : PHP 스크립트가 노출되어 인터넷에서 악의적으로 잠재적으로 사용할 수 있다고 지적했습니다. 이것을 처리하는 백만 가지 방법이 있습니다. 가장 단순한 URL 난독 화 중 하나입니다 ... 보안 PHP 사례는 별도의 Google 자격이 있습니다 .P

편집-2 : 대중의 요구에 따라 PHP 스크립트가 아닌 이미지인지 확인하기 위해 검사를 추가했습니다 (보낸 사람 : 파일이 이미지 인 경우 PHP 확인 ).


15
또한 로컬 파일 시스템에서 이미지와 스크립트를로드 할 때 동일한 문제가 발생합니다.
Guy Dafny

2
누군가가 PHP 스크립트를 사용하여 서버에 큰 파일을 악의적으로 넘치게 만들 수있는 것은 안전하지 않습니다.
LAX1DUDE

1
@ LAX1DUDE 답변은 간단한 보안 점검으로 개선되었습니다
jumpjack

1
이 방법 덕분에 node.js를 사용하지 않고 이미지를 tesseract.js OCR 엔진에 전달할 수도 있습니다 (img.onload () 함수에서 Tesseract.recognize (img)에 호출을 추가하십시오)
jumpjack

1
사용자가 제공 한 파일 이름, 파일 / 마임 유형, 업로드 위치 및 크기를 확인해야합니다. 이 코드는 여러 공격에 취약합니다. 나는 그것을 독자에게 연습으로 남겨 두지만이 코드를 사용하여 .php 파일을 웹 서버의 루트에 업로드 할 수 있다고 생각합니다.
hiburn

4

Chrome코드를 로컬에서 테스트하는 동안 이 오류가 발생했습니다 . 전환했는데 Firefox더 이상 오류가 표시되지 않습니다. 다른 브라우저로 전환하는 것이 빠른 해결책 일 수 있습니다.

첫 번째 답변에서 제공된 솔루션을 사용하는 경우 변수 img.crossOrigin = "Anonymous";를 선언 한 직후 img(예 :) 추가해야합니다 var img = new Image();.


2

문제는 다른 도메인에서 의미하는 외부 이미지를로드한다는 것입니다. 캔버스 컨텍스트의 데이터에 액세스하려고하면 보안 오류가 발생합니다.


예, 업로드 하위 도메인에서 이미지를 얻습니다 ... 어떻게해야합니까?
Erfan Safarpoor

1
프록시를 사용하여 이미지를 검색 할 수 있습니다.이 프록시는 캔버스를 실행하는 도메인과 동일한 도메인에 있습니다.
axelduch

1
내 컴퓨터에서 새 이미지를 업로드하고 캔버스에로드하려고하는데이 오류가 발생합니다. 서버 이미지를 사용하고 있지 않습니다.
Piyush Dholariya

캔버스에 복사 된 이미지가 컴퓨터에서 생성되고 스크립트가 실제로 실행되는 스크립트는 외부 도메인으로 스크립트가있는 서버에서 컴퓨터를 볼 수 있습니다.
jumpjack

2

교차 원점 도메인에서로드하여 캔버스를 "오염"시킵니다. 이 MDN 기사를 확인하십시오.

https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image


<IfModule mod_setenvif.c> <IfModule mod_headers.c> <FilesMatch "\. (cur | gif | ico | jpe? g | png | svgz? | webp) $"> SetEnvIf Origin ":"IS_CORS 헤더 세트 액세스- Control-Allow-Origin "*"env = IS_CORS </ FilesMatch> </ IfModule> </ IfModule> 모든 도메인에 htaccess하지만 작동하지 않습니다!
Erfan Safarpoor

1
어떤 브라우저에서 테스트하고 있습니까? 그리고 Apache를 다시 시작했는지 확인하십시오.
srquinn

아파치를 다시 시작할 수 없습니다 ... 공유 cpanel 계정이 있습니다.
Erfan Safarpoor 2014

2
Apache 설정을 구성 할 수 없습니다. 죄송합니다. 또한이 질문의 범위를 벗어납니다. Apache 설정과 관련된 문제를 새로운 질문에 게시하면 커뮤니티에서 기꺼이 도와 드리겠습니다.
srquinn

1

로컬에서 작업 할 때 서버 추가

현지에서 일할 때 비슷한 문제가 발생했습니다. url은 로컬 파일의 경로가됩니다 (예 : file : ///Users/PeterP/Desktop/folder/index.html).

MAC에 있습니다.

http-server를 전 세계적으로 설치 하여이 문제를 해결했습니다. https://www.npmjs.com/package/http-server

단계 :

  1. 글로벌 설치 : npm install http-server -g
  2. 서버를 실행하십시오. http-server ~/Desktop/folder/

추신 : 노드가 설치되어 있다고 가정합니다. 그렇지 않으면 npm 명령을 실행하지 않아도됩니다.


0

matt burns가 그의 답변 에서 언급했듯이 문제 이미지가 호스팅되는 서버에서 CORS를 활성화해야 할 수도 있습니다.

서버가 Apache 인 경우 다음 스 니펫 ( 여기에서 )을 VirtualHost 구성 또는 .htaccess파일 에 추가하여이를 수행 할 수 있습니다 .

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

... VirtualHost에 추가하는 경우 Apache의 구성도 다시로드해야합니다 (예 : sudo service apache2 reloadApache가 Linux 서버에서 실행중인 경우).


0

내 문제가 너무 엉망이되어 CORS 문제가 발생하지 않도록 이미지를 base64로 인코딩했습니다.


-2

나는 오늘 같은 문제를 겪고 코드에 따라 해결합니다.

html 코드 :

<div style='display: none'>
  <img id='img' src='img/iak.png' width='600' height='400' />
</div>
<canvas id='iak'>broswer don't support canvas</canvas>

JS 코드 :

var canvas = document.getElementById('iak')
var iakImg = document.getElementById('img')
var ctx = canvas.getContext('2d')
var image = new Image()
image.src=iakImg.src
image.onload = function () {
   ctx.drawImage(image,0,0)
   var data = ctx.getImageData(0,0,600,400)
}

위와 같은 코드를 사용하고 도메인 간 문제는 없습니다.


1
src 값은 여전히 ​​교차 출처 소스이므로 어떻게 문제를 피할 수 있습니까?
Loveen Dyall 2016

이 방법은 file : /// X : /htmlfile.html과 같은 로컬 html 파일 (서버 없음)을 실행할 때 작동합니다. 대부분의 사람들은 ";"로 진술을 끝냅니다. "var data = .."의 요점은 무엇입니까? "도메인 간"오류가 발생하지 않는 이유를 설명하고 싶습니다. 그러나 감사합니다.
dcromley

더블 스마트 카리
마리 셀반

1
@dcromley "대부분의 사람들은; 표준에 따라 세미콜론을 사용하지 않는 것이 좋습니다. 세미콜론은 더 많은 작업을 추가하고 추악하게 보이고 코드는 완벽하게 작동합니다. 확인 github.com/standard/standard은
madprops

1
@madprops developer.mozilla.org는 "자바 스크립트 애플리케이션은 적절한 구문을 가진 문장으로 구성되어 있습니다. 단일 문장은 여러 줄에 걸쳐있을 수 있습니다. 각 문장이 세미콜론으로 구분되면 단일 문장에서 여러 문장이 발생할 수 있습니다. 키워드가 아닙니다. 키워드 그룹에 속합니다. " 그래서 나는 "항상 사용"파벌에 있습니다. 나는 "never"진영이 있다는 것을 몰랐다. 나는 후자가 지구가 평평하다고 믿는다 고 생각합니까? (그냥 농담-감사합니다)
dcromley

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