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.