XmlHttpRequest 오류 : Access-Control-Allow-Origin에서 Origin null을 사용할 수 없습니다.


550

jQuery의 AJAX 지원을 통해 Flickr 및 Panoramio에서 이미지를 가져 오는 페이지를 개발 중입니다.

Flickr 측은 정상적으로 작동하지만 $.get(url, callback)Panoramio에서 시도 할 때 Chrome 콘솔에 오류가 표시됩니다.

XMLHttpRequest는 http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150 로드 할 수 없습니다 . Access-Control-Allow-Origin에서는 원점 널을 사용할 수 없습니다.

브라우저에서 해당 URL을 직접 쿼리하면 정상적으로 작동합니다. 무슨 일이 일어나고 있습니까? 내 쿼리를 잘못 작성하고 있습니까, 아니면 Panoramio가 내가하려는 일을 방해하기 위해하는 일입니까?

Google은 오류 메시지 에서 유용한 일치 항목을 찾지 못했습니다 .

편집하다

다음은 문제를 보여주는 샘플 코드입니다.

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=processImages&minx=-30&miny=0&maxx=0&maxy=150';

  $.get(url, function (jsonp) {
    var processImages = function (data) {
      alert('ok');
    };

    eval(jsonp);
  });
});

온라인에서 예제실행할 수 있습니다 .

편집 2

이에 대한 도움을 주신 Darin에게 감사드립니다. 위의 코드가 잘못되었습니다. 대신 이것을 사용하십시오 :

$().ready(function () {
  var url = 'http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&minx=-30&miny=0&maxx=0&maxy=150&callback=?';

  $.get(url, function (data) {
    // can use 'data' in here...
  });
});

1
무엇합니까 당신이 요청하게되는 경우 URL은 에서를 ? 이것은 동적으로 생성 될 수 발생하지 않습니다 iframe당신이 document.write예를 들어,에?
Pekka

5
요청에서 각 서비스로 HTTP 응답을 게시 할 수 있습니까? Panoramio는 Access-Control-Allow-Origin을 제공하지 않습니다. 예제는 w3.org/TR/cors 를 참조하십시오 .
Kevin Hakanson

2
@Kevin, 서버가 JSONP를 보내는 경우 해당 헤더가 필요하지 않습니다.
Darin Dimitrov

@Pekka, 현재 로컬 컴퓨터에서 페이지를 실행하고 있습니다 ( file:///C:/). iframe참여 하지 않습니다 .
Drew Noakes

1
@http URL에서 실행하면 어떻게됩니까? 이런 식으로 차이를 만들지 말고 가능성을 배제해야합니다.
Pekka

답변:


423

기록을 위해, 내가 알 수있는 한 두 가지 문제가 있습니다.

  1. "jsonp"형식 지정자를에 전달하지 않았 $.get으므로 일반 XMLHttpRequest를 사용하고있었습니다. 그러나 브라우저는 서버가 확인한 경우 도메인 간 XMLHttpRequest를 허용하도록 CORS (Cross-Origin Resource Sharing)를 지원했습니다. Access-Control-Allow-Origin헤더가 들어온 곳 입니다.

  2. file : // URL에서 실행한다고 언급했다고 생각합니다. CORS 헤더가 도메인 간 XHR이 정상임을 알리는 두 가지 방법이 있습니다. 하나는 Access-Control-Allow-Origin: *(당신이 Flickr를 통해 Flickr에 도달했다면 $.get, 그들이하고 있었을 것임) 보내는 것이고, 다른 하나는 Origin헤더 의 내용을 에코하는 것 입니다. 그러나 file://URL은 null Origin을 생성하여 에코 백을 통해 승인 할 수 없습니다.

첫 번째는 Darin의 사용 제안에 의해 로터리 방식으로 해결되었습니다 $.getJSON. callback=?URL에 하위 문자열이 있으면 요청 유형을 기본값 인 "json"에서 "jsonp"로 변경하는 것은 약간의 마술 입니다.

더 이상 file://URL 에서 CORS 요청을 수행하려고 시도하여 두 번째 문제를 해결했습니다 .

다른 사람을 명확히하기 위해 간단한 문제 해결 지침은 다음과 같습니다.

  1. JSONP를 사용하려는 경우 다음 중 하나에 해당해야합니다.
    • 사용 $.get하고로 설정 dataType했습니다 jsonp.
    • URL을 사용 중이며 URL에 $.getJSON포함 callback=?되어 있습니다.
  2. CORS를 통해 도메인 간 XMLHttpRequest를 수행하려는 경우 ...
    1. 를 통해 테스트하고 있는지 확인하십시오 http://. 통해 실행되는 스크립트 file://는 CORS를 제한적으로 지원합니다.
    2. 브라우저가 실제로 CORS를 지원 하는지 확인하십시오 . (오페라와 인터넷 익스플로러는 파티에 늦었다)

45
그래서 이것에 대한 해결책은 무엇입니까?
jQuerybeast

19
콜백 =? FTW
Tim

10
크롬과 같은 일부 브라우저는 --allow-file-access-from-files 매개 변수로 시작한 경우 CORS를 허용합니다
echox

1
callback=?나를 위해 작동 jsonp=?하지 않았다. 그것에 대한 설명이 있습니까?
crunkchitis

1
테스트하려면 웹 서버를 설치해야 http://합니까? 아니면 해당 프로토콜을 사용하여 파일을 간단하게 여는 방법이 있습니까?
Will Sewell

76

호출 된 스크립트에 HEADER를 추가해야 할 수도 있습니다. 여기 PHP에서해야 할 작업이 있습니다.

header('Access-Control-Allow-Origin: *');

도메인 간 AJAX ou services WEB (프랑스어)에 대한 자세한 내용 .


1
@Uri : HTTP 서버에 따라 다릅니다. Apache를 사용하면 mod_headers를 살펴볼 수 있습니다.
ssokolow

4
@Uri <meta http-equiv = "Access-Control-Allow-Origin"content = "*">
Herberth Amaral

7
@HerberthAmaral <head> </ head> 안에 이것을 추가하려고 시도했지만 작동하지 않습니다. iOS Safari 및 Chrome에서 시도하고 있지만 콘솔에서 Access-Control-Allow-Origin 오류로 인해 null이 허용되지 않습니다.
thandasoru

3
보안상의 이유로 html 파일 헤드에서는 작동하지 않습니다. 헤더 여야합니다. stackoverflow.com/questions/7015782/…
저스틴 블랭크

HTML에있을 수 없습니다. 네트워크 (웹 서버라고 함)를 통해 HTML 페이지를 브라우저로 보내는 프로그램에서 지정해야합니다.
Roman Plášil

70

간단한 HTML 프로젝트의 경우 :

cd project
python -m SimpleHTTPServer 8000

그런 다음 파일을 찾아보십시오.


1
멋지고 작동하는 동안 0.0.0.0:8000으로 이동하여 POSTGoogle에 code 501, message Unsupported method ('POST')대한 요청을 시도 하십시오.
pjammer

"예를 들어 cherrypy와 같은 Python 웹 서버가 0.0.0.0에서 서비스를 제공한다고하면 요청 된 호스트 이름 또는 IP에 관계없이 해당 시스템에서 발생하는 모든 TCP 트래픽을 수신하고 있음을 의미합니다." 그래서 어쩌면 로컬 호스트에 게시하려고 : 8000 stackoverflow.com/a/4341808/102022을
eric.christensen

20

Chrome v5.0.375.127에서 작동합니다 (알림이 표시됨).

$.get('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150',
function(json) {
    alert(json.photos[1].photoUrl);
});

또한 $.getJSON()이전 버전은 IE8 (적어도 내 컴퓨터에서는)에서 작동하지 않으므로 대신 메소드 를 사용하는 것이 좋습니다 .

$.getJSON('http://www.panoramio.com/wapi/data/get_photos?v=1&key=dummykey&tag=test&offset=0&length=20&callback=?&minx=-30&miny=0&maxx=0&maxy=150', 
function(json) {
    alert(json.photos[1].photoUrl);
});

여기에서 온라인으로 사용해 볼 수 있습니다 .


최신 정보:

코드를 보여 주었으므로 문제가 있음을 알 수 있습니다. 익명 함수와 인라인 함수를 모두 가지고 있지만 둘 다 호출 processImages됩니다. 이것이 jQuery의 JSONP 지원이 작동하는 방식입니다. callback=?익명 함수를 사용할 수 있도록 정의하는 방법에 주목하십시오 . 자세한 내용은 설명서를 참조하십시오 .

또 다른 언급은 eval을 호출해서는 안된다는 것입니다. 익명 함수에 전달 된 매개 변수는 이미 jQuery에 의해 JSON으로 구문 분석됩니다.


흠 확인 다시 시도하겠습니다. 다른 버전의 Chrome btw "6.0.472.51 베타"를 사용하고 있습니다.
Drew Noakes

귀하의 코드가 저에게 효과적이었습니다. 그래도 문제를 이끌어내는 코드로 내 질문을 업데이트했습니다.
Drew Noakes

get getJSON 주셔서 감사합니다 ... jsFiddle 예제를 포크하여 문제를 보여 주었고 ( jsfiddle.net/ZfvKm ) 이제 XMLHttpRequest가 panoramio.com/wapi/data/…
Drew Noakes

@Darin, 업데이트 주셔서 감사합니다. 나는 당신의 요점을보고, 이것의 몇 가지 조합으로 연주했지만 반환 된 객체에 액세스하는 방법을 아직 찾지 못했습니다. 데이터 액세스를 표시하도록 jsFiddle 예제를 업데이트 할 수 있습니까? 콜백을 설정하면 ?반환 된 JSON은 괄호로 묶습니다. 콜백 함수에 대한 매개 변수를 정의하지 않았으며의 값에 this응답 객체가없는 것 같습니다 (최소한 .data값은 null).
Drew Noakes

@Darin, 환상적입니다. 많은 감사합니다. 지금 잘 작동합니다. 이 글을 읽는 사람 callback=?은 jQuery에 내부에 임의의 함수 이름을 생성하도록 지시하여 사용자가 전달하는 익명 함수를 호출합니다 .getJSON. 감사합니다.
Drew Noakes

8

요청 된 서버가 JSON 데이터 형식을 지원하는 한 JSONP (JSON Padding) 인터페이스를 사용하십시오. 프록시 서버 나 멋진 헤더를 사용하지 않고도 외부 도메인 요청을 할 수 있습니다.



4

http.conf파일을 통해 파일을 관리했습니다 (HTTP 서비스를 편집 한 후 다시 시작).

<Directory "/home/the directory_where_your_serverside_pages_is">
    Header set Access-Control-Allow-Origin "*"
    AllowOverride all
    Order allow,deny
    Allow from all
</Directory>

에서 Header set Access-Control-Allow-Origin "*", 당신은 정확한 URL을 넣을 수 있습니다.


1
XAMPP의 Apache에서는 작동하지 않습니다. 문제는 여전히 존재합니다.
랩터

1
안전하지 않습니다. 이유를 여기에서보십시오. stackoverflow.com/questions/7564832/…
Rob

@RobQuist가 말한 것처럼 안전하지 않습니다.
d337

4

로컬 테스트를 수행하거나 파일을 호출하는 경우 file://브라우저 보안을 비활성화해야합니다.

MAC에서 : open -a Google\ Chrome --args --disable-web-security


3

필자의 경우 동일한 코드가 Firefox에서는 잘 작동했지만 Chrome에서는 제대로 작동하지 않았습니다. 구글 크롬의 자바 스크립트 콘솔은 다음과 같이 말했다.

XMLHttpRequest cannot load http://www.xyz.com/getZipInfo.php?zip=11234. 
Origin http://xyz.com is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"

Ajax URL의 www 부분을 원본 URL과 올바르게 일치시키기 위해 www 부분을 삭제해야했고 잘 작동했습니다.


2

모든 서버가 jsonp를 지원하는 것은 아닙니다. 서버는 결과에 콜백 함수를 설정해야합니다. 순수한 json을 반환하지만 jsonp를 지원하지 않는 사이트에서 json 응답을 얻는 데 이것을 사용합니다.

function AjaxFeed(){

    return $.ajax({
        url:            'http://somesite.com/somejsonfile.php',
        data:           {something: true},
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

function GetData() {
    AjaxFeed()

    /* Everything worked okay. Hooray */
    .done(function(data){
        return data;
    })

    /* Okay jQuery is stupid manually fix things */
    .fail(function(jqXHR) {

        /* Build HTML and update */
        var data = jQuery.parseJSON(jqXHR.responseText);

        return data;
    });
}

1

Apache 서버를 사용하므로 mod_proxy 모듈을 사용했습니다. 모듈 활성화 :

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

그런 다음 다음을 추가하십시오.

ProxyPass /your-proxy-url/ http://service-url:serviceport/

마지막으로 proxy-url을 스크립트에 전달하십시오.


1

최종 참고로 모질라 문서는 명시 적으로 말한다 것을

헤더가 와일드 카드 된 경우 위의 예는 실패합니다. Access-Control-Allow-Origin : *. Access-Control-Allow-Origin이 http : //foo.example을 명시 적으로 언급 하므로 자격 증명 인식 컨텐츠가 호출 웹 컨텐츠로 리턴됩니다.

결과적으로 단순히 '*'를 사용하는 것은 나쁜 습관이 아닙니다. 단순히 작동하지 않습니다 :)


1

PHP의 경우-Chrome, Safari 및 Firefox에서 작동합니다.

https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null

header('Access-Control-Allow-Origin: null');

file : //로 axios call PHP 라이브 서비스 사용


이것은 또한 나에게서 작동합니다. null이 실제 NULL이 아닌 STRING인지 확인하십시오. 나는 header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);원격 서버에서 다른 서버로의 교차 원점을 허용하고 로컬 파일의 경우 (문자열) null로 넘어갑니다.
루이 Loudog Trottier

0

Chrome에서도 동일한 오류가 발생했습니다 (다른 브라우저는 테스트하지 않았습니다). www.domain.com 대신 domain.com을 탐색했기 때문입니다. 조금 이상하지만 .htaccess에 다음 줄을 추가하여 문제를 해결할 수 있습니다. domain.com을 www.domain.com으로 리디렉션하고 문제가 해결되었습니다. 나는 게으른 웹 방문자이므로 www를 거의 입력하지 않지만 분명히 어떤 경우에는 필요합니다.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

0

최신 버전의 JQuery를 사용하고 있는지 확인하십시오. JQuery 1.10.2에서이 오류가 발생했으며 JQuery 1.11.1을 사용한 후 오류가 해결되었습니다.


0

사람들,

비슷한 문제가 발생했습니다. 그러나 Fiddler를 사용하여 문제를 해결할 수있었습니다. 문제는 웹 API 측의 CORS 구현에서 구성된 클라이언트 URL에 슬래시가 없어야한다는 것입니다. Chrome을 통해 요청을 제출 하고 헤더TextView 탭을 검사 한 후 Fiddler 섹션 후 오류 메시지는 다음과 같습니다.

* "지정된 정책 출처 your_client_url : / '이 잘못되었습니다. 슬래시로 끝날 수 없습니다."

Internet Explorer에서 아무런 문제없이 작동했지만 Chrome을 사용하여 테스트 할 때 두통을 겪었습니다.

CORS 코드에서 슬래시를 제거하고 웹 API를 다시 컴파일했으며 이제 Chrome 및 Internet Explorer를 통해 문제없이 API에 액세스 할 수 있습니다. 이 기회를주세요.

고마워 앤디


0

위의 CodeGroover가 게시 솔루션에는 작은 문제가 있습니다. 파일을 변경하면 실제로 업데이트 된 파일을 사용하기 위해 서버를 다시 시작해야합니다 (적어도 필자의 경우).

그래서 조금 검색하면 것을 발견 했습니다 .

sudo npm -g install simple-http-server # to install
nserver # to use

그리고 그것은에서 봉사 할 것 http://localhost:8000입니다.


1
이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다. - 리뷰에서
Vi100

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