jQuery AJAX 크로스 도메인


477

다음은 test.php와 testserver.php의 두 페이지입니다.

test.php

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
    $(function() {
        $.ajax({url:"testserver.php",
            success:function() {
                alert("Success");
            },
            error:function() {
                alert("Error");
            },
            dataType:"json",
            type:"get"
        }
    )})
</script>

testserver.php

<?php
$arr = array("element1",
             "element2",
             array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>

이제 내 문제 :이 두 파일이 같은 서버 (localhost 또는 웹 서버)에 있으면 작동하고 alert("Success")호출됩니다. 웹 서버의 testserver.php와 localhost의 test.php를 의미하는 다른 서버에 있으면 작동하지 않고 alert("Error")실행 중입니다. ajax 내부의 URL이 http://domain.com/path/to/file/testserver.php 로 변경된 경우에도


38
들르는 사람들을 위해. 크로스 도메인 자바 스크립트 작업 호출하는 방법을 생각하려면이 읽기 stackoverflow.com/a/11736771/228656을
— 압둘 Munim

1
이 질문에 대한 답을 여기에 작성했습니다. jQuery AJAX를 사용하여 크로스 도메인 HTML 페이지로드 – 마지막, https 지원
— jherax

답변:


412

JSONP를 사용하십시오 .

jQuery :

$.ajax({
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     success:function(json){
         // do stuff with json (in this case an array)
         alert("Success");
     },
     error:function(){
         alert("Error");
     }      
});

PHP :

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>

에코가 잘못되었을 수 있습니다. PHP를 사용한 지 오래되었습니다. 어쨌든 callbackName('jsonString')따옴표 를 출력해야 합니다. jQuery는 자체 콜백 이름을 전달하므로 GET 매개 변수에서 가져와야합니다.

Stefan Kendall이 게시 한 것처럼 $ .getJSON () 은 속기 방법이지만 'callback=?'URL에 GET 매개 변수로 추가해야합니다 (예, 값은?, jQuery는 이것을 자체 생성 된 콜백 메소드로 바꿉니다).


2
왜 callbackName('/* json */')대신에 귀국해야 callbackName(/* json */)합니까?
— Eric

3
@eric 콜백에는 JSON 문자열이 필요합니다. 이론적으로 객체도 작동하지만 jQuery가 어떻게 응답하는지 확실하지 않으면 오류가 발생하거나 자동으로 실패 할 수 있습니다.
— BGerrissen

다음과 같은 오류가 발생합니다. SyntaxError : 누락; 명령문 { "ResultCode": 2} 이전. 여기서 { "ResultCode": 2}는 응답입니다. 조언을 부탁드립니다.
— user2003356

@ user2003356은 JSONP 대신 일반 JSON을 반환하는 것처럼 보입니다. callbackFunction ({ "ResultCode": 2})와 같은 것을 반환해야합니다. jQuery는 GET 매개 변수 'callback'을 요청에 추가합니다. 이는 jquery가 사용하는 콜백 함수의 이름이며 응답에 추가되어야합니다.
— BGerrissen

2
CORS는 이제 해킹으로 만 설명 할 수있는 JSONP와 달리 널리 지원되는 표준입니다. 아래의 @joshuarh의 답변이 지금 선호되는 답변이어야합니다.
— Vicky Chijwani

202

JSONP는 좋은 옵션이지만 더 쉬운 방법이 있습니다. Access-Control-Allow-Origin서버에서 간단히 헤더를 설정할 수 있습니다 . *모든 도메인의 도메인 간 AJAX 요청을 수락 하도록 설정 합니다. ( https://developer.mozilla.org/en/http_access_control )

이를 수행하는 방법은 물론 언어마다 다릅니다. 여기 레일스에 있습니다.

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end

이 예에서 say_hello작업은 모든 도메인의 AJAX 요청을 수락하고 "hello!"응답을 반환합니다.

다음은 반환 할 수있는 헤더의 예입니다.

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive

그대로, 일부 브라우저 제한이 있습니다. http://caniuse.com/#feat=cors를 참조 하십시오 .


12
Jsonp는 게시, 넣기 및 삭제를 지원하지 않았습니다. 귀하의 솔루션은 훌륭하게 작동합니다.
— TonyTakeshi

35
PHP 헤더에서 ( "Access-Control-Allow-Origin : *");
— SparK September

9
@Warrior jQuery의 .post()방법을 사용하는 경우 jQuery에서 도메인 간 지원을 활성화해야합니다. 이 작업은 다음과 같습니다 $.support.cors = true..
— Friederike

21
이 방법으로 서버를 구성 할 때의 보안 영향은 무엇입니까?
— Jon Schneider

19
wilcard "*"를 사용하는 대신 데이터를 공유하려는 도메인 만 허용하는 것이 좋습니다.
— Sebastián Grignoli

32

Access-Control-Allow-Origin 을 추가하여 HTTP 헤더를 통해이를 제어 할 수 있습니다 . *로 설정하면 모든 도메인의 도메인 간 AJAX 요청을 수락합니다.

PHP를 사용하면 정말 간단합니다. 도메인 외부에서 액세스하려는 스크립트에 다음 줄을 추가하십시오.

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

httpd.conf에서 mod_headers 모듈을 활성화하는 것을 잊지 마십시오.


당신은 내 하루를 구했다.
— NomanJaved

20

동일 출처 정책을 살펴 봐야합니다 .

컴퓨팅에서 동일한 출처 정책은 JavaScript와 같은 여러 브라우저 측 프로그래밍 언어에 대한 중요한 보안 개념입니다. 이 정책은 동일한 사이트에서 시작된 페이지에서 실행되는 스크립트가 특별한 제한없이 서로의 메서드 및 속성에 액세스 할 수 있도록하지만 다른 사이트의 페이지에서 대부분의 메서드 및 속성에 액세스 할 수는 없습니다.

데이터를 얻을 수 있으려면 다음과 같아야합니다.

동일한 프로토콜 및 호스트

해결 하려면 JSONP 를 구현해야 합니다.


17

로컬 디스크 "file : /// C : /test/htmlpage.html"에서 웹 페이지를로드하고 "http : //localhost/getxml.php"url을 호출하여 IE8 + 및 Firefox12 + 브라우저에서 jQuery v1을 사용하여 웹 페이지를로드해야했습니다. .7.2 상용구 코드를 최소화하는 lib. 수십 개의 기사를 읽은 후 마침내 알아 냈습니다. 여기 내 요약이 있습니다.

  • 서버 스크립트 (.php, .jsp, ...)는 http 응답 헤더 Access-Control-Allow-Origin을 반환해야합니다. *
  • jQuery 아약스를 사용하기 전에 자바 스크립트에서이 플래그를 설정하십시오. jQuery.support.cors = true;
  • jQuery ajax 함수를 사용하기 전에 한 번 또는 매번 플래그를 설정할 수 있습니다
  • 이제 IE와 Firefox에서 .xml 문서를 읽을 수 있습니다. 내가 테스트하지 않은 다른 브라우저.
  • 응답 문서는 일반 / 텍스트, xml, json 또는 기타 모든 것이 될 수 있습니다.

다음은 디버그 sysout이 포함 된 jQuery ajax 호출 예제입니다.

jQuery.support.cors = true;
$.ajax({
    url: "http://localhost/getxml.php",
    data: { "id":"doc1", "rows":"100" },
    type: "GET",
    timeout: 30000,
    dataType: "text", // "xml", "json"
    success: function(data) {
        // show text reply as-is (debug)
        alert(data);

        // show xml field values (debug)
        //alert( $(data).find("title").text() );

        // loop JSON array (debug)
        //var str="";
        //$.each(data.items, function(i,item) {
        //  str += item.title + "\n";
        //});
        //alert(str);
    },
    error: function(jqXHR, textStatus, ex) {
        alert(textStatus + "," + ex + "," + jqXHR.responseText);
    }
});

1
이 질문에 대한 답변을 여기에 작성했습니다. jQuery AJAX를 사용하여 크로스 도메인 html 페이지로드 – 마지막 하나는 https를 지원합니다
— jherax

가장 중요한 점 : PHP에서 다음 줄을 스크립트에 추가하십시오.header("Access-Control-Allow-Origin: *");
— T30

1
@ whome 당신의 답변에 대단히 감사합니다. 당신은 저를 많이 도와주었습니다. 건배.
— Luis Milanese

10

동일한 출처 정책으로 인해 JavaScript가 여러 도메인에서 요청하는 것을 막을 수는 있지만 CORS 사양은 원하는 API 액세스 유형 만 허용하며 현재 주요 브라우저 모음에서 지원됩니다.

클라이언트 및 서버에 대해 출처 간 자원 공유를 사용하는 방법을 참조하십시오.

http://enable-cors.org/

"CORS (Cross-Origin Resource Sharing)는 도메인 경계를 넘어 진정한 개방형 액세스를 가능하게하는 사양입니다. 공용 컨텐츠를 제공하는 경우 CORS를 사용하여 범용 JavaScript / 브라우저 액세스를 위해 열어보십시오."



9

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을 스크립트에 전달하십시오.


8

브라우저 보안은 한 도메인에 호스팅 된 페이지에서 다른 도메인에 호스팅 된 페이지로 아약스 호출을 방지합니다. 이것을 " 동일 출처 정책 "이라고합니다.



4

Jquery 문서에서 ( link ) :

  • 브라우저 보안 제한으로 인해 대부분의 "Ajax"요청에는 동일한 오리진 정책이 적용됩니다. 요청이 다른 도메인, 하위 도메인 또는 프로토콜에서 데이터를 성공적으로 검색 할 수 없습니다.

  • 스크립트 및 JSONP 요청에는 동일한 원본 정책 제한이 적용되지 않습니다.

따라서 요청에 jsonp를 사용해야한다고 생각합니다. 그러나 이것을 직접 시도하지 않았습니다.


2

문제를 해결하는 3 가지 방법을 알고 있습니다.

  1. 먼저 두 도메인에 모두 액세스 할 수있는 경우 다음을 사용하여 다른 모든 도메인에 대한 액세스를 허용 할 수 있습니다.

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

    또는 .htaccess 파일에 코드를 추가하여 도메인 만 :

    <FilesMatch "\.(ttf|otf|eot|woff)$"> <IfModule mod_headers.c> SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> </FilesMatch>

  2. 서버의 PHP 파일에 ajax 요청을 하고이 PHP 파일을 사용하여 다른 도메인에 대한 요청을 처리 할 수 ​​있습니다.

  3. jsonp는 권한이 필요하지 않기 때문에 사용할 수 있습니다. 이를 위해 당신은 우리의 친구 @BGerrissen 답변을 읽을 수 있습니다.

0

Microsoft Azure의 경우 약간 다릅니다.

Azure에는 설정해야하는 특수 CORS 설정이 있습니다. 본질적으로 뒤에서 똑같지 만 joshuarh가 언급 한 헤더를 설정하면 작동하지 않습니다. 도메인 간 사용을위한 Azure 설명서는 다음에서 찾을 수 있습니다.

https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript

호스팅 플랫폼 에이 특별한 설정이 있음을 깨닫기 전에 몇 시간 동안이 문제를 해결했습니다.


0

작동합니다. 필요한 모든 것 :

PHP :

header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

JS (jQuery 아약스) :

var getWBody = $.ajax({ cache: false,
        url: URL,
        dataType : 'json',
        type: 'GET',
        xhrFields: { withCredentials: true }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.