jQuery AJAX domänenübergreifend

477

Hier sind zwei Seiten, test.php und 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);
?>

Nun mein Problem: Wenn sich beide Dateien auf demselben Server befinden (entweder localhost oder Webserver), funktioniert es und alert("Success")wird aufgerufen. Wenn es sich auf verschiedenen Servern befindet, dh testserver.php auf dem Webserver und test.php auf localhost, funktioniert es nicht und alert("Error")wird ausgeführt. Auch wenn die URL in Ajax in http://domain.com/path/to/file/testserver.php geändert wird

Firose Hussain
quelle
38
Für Leute, die vorbeischauen. Lesen Sie dies, um eine Vorstellung davon zu bekommen, wie domänenübergreifende Javascript-Aufrufe funktionieren stackoverflow.com/a/11736771/228656
Abdul Munim
1
Ich habe hier eine Antwort auf diese Frage geschrieben: Laden einer domänenübergreifenden HTML-Seite mit jQuery AJAX - die letzte, unterstützt https
jherax

Antworten:

412

Verwenden Sie 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).");";
?>

Das Echo könnte falsch sein, es ist schon eine Weile her, seit ich PHP verwendet habe. In jedem Fall müssen Sie callbackName('jsonString')die Anführungszeichen beachten. jQuery übergibt seinen eigenen Rückrufnamen, daher müssen Sie diesen von den GET-Parametern abrufen.

Und wie Stefan Kendall gepostet hat, ist $ .getJSON () eine Kurzmethode , aber dann müssen Sie 'callback=?'die URL als GET-Parameter anhängen (ja, Wert ist ?, JQuery ersetzt dies durch eine eigene generierte Rückrufmethode).

BGerrissen
quelle
2
Warum müssen Sie callbackName('/* json */')statt zurückkehren callbackName(/* json */)?
Eric
3
@eric Der Rückruf erwartet eine JSON-Zeichenfolge. Theoretisch könnte ein Objekt auch funktionieren, aber nicht sicher, wie jQuery darauf reagiert, es könnte einen Fehler auslösen oder stillschweigend fehlschlagen.
BGerrissen
Ich erhalte den folgenden Fehler. SyntaxError: fehlt; vor Anweisung {"ResultCode": 2}. Wobei {"ResultCode": 2} die Antwort ist. Bitte beraten.
user2003356
@ user2003356 sieht so aus, als würden Sie einfaches JSON anstelle von JSONP zurückgeben. Sie müssen Folgendes zurückgeben: callbackFunction ({"ResultCode": 2}). jQuery fügt der Anforderung den GET-Parameter 'callback' hinzu. Dies ist der Name der Rückruffunktion, die jquery verwendet und der Antwort hinzugefügt werden sollte.
BGerrissen
2
Es ist 2016. CORS ist jetzt ein weit verbreiteter Standard, im Gegensatz zu JSONP, das nur als Hack bezeichnet werden kann. Die Antwort von @ joshuarh unten sollte jetzt die bevorzugte sein.
Vicky Chijwani
202

JSONP ist eine gute Option, aber es gibt einen einfacheren Weg. Sie können den Access-Control-Allow-OriginHeader einfach auf Ihrem Server festlegen . Wenn Sie diese Option festlegen, *werden domänenübergreifende AJAX-Anforderungen von jeder Domäne akzeptiert. ( https://developer.mozilla.org/en/http_access_control )

Die Methode dazu variiert natürlich von Sprache zu Sprache. Hier ist es in Rails:

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

In diesem Beispiel say_helloakzeptiert die Aktion AJAX-Anforderungen von jeder Domain und gibt die Antwort "Hallo!" Zurück.

Hier ist ein Beispiel für die Header, die möglicherweise zurückgegeben werden:

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

So einfach es ist, es gibt einige Browser-Einschränkungen. Siehe http://caniuse.com/#feat=cors .

Joshuarh
quelle
12
Jsonp unterstützte das Posten, Setzen und Löschen nicht. Ihre Lösung funktioniert hervorragend.
TonyTakeshi
35
im PHP-Header ("Access-Control-Allow-Origin: *");
SparK
9
@Warrior Wenn Sie die .post()Methode von jQuery verwenden, müssen Sie die domänenübergreifende Unterstützung in jQuery aktivieren. Damit ist fertig : $.support.cors = true.
Friederike
21
Welche Auswirkungen hat die Konfiguration eines Servers auf diese Weise auf die Sicherheit?
Jon Schneider
19
Es ist besser, nur die Domänen zuzulassen, für die Sie die Daten freigeben möchten, anstatt die wilcard "*" zu verwenden.
Sebastián Grignoli
32

Sie können dies über den HTTP-Header steuern, indem Sie Access-Control-Allow-Origin hinzufügen . Wenn Sie * festlegen, werden domänenübergreifende AJAX-Anforderungen von jeder Domäne akzeptiert.

Mit PHP ist es ganz einfach: Fügen Sie einfach die folgende Zeile in das Skript ein, auf das Sie außerhalb Ihrer Domain zugreifen möchten:

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

Vergessen Sie nicht, das Modul mod_headers in httpd.conf zu aktivieren.

Adorjan Princz
quelle
du hast meinen Tag gerettet.
NomanJaved
20

Sie müssen sich die Same Origin Policy ansehen :

Beim Rechnen ist dieselbe Ursprungsrichtlinie ein wichtiges Sicherheitskonzept für eine Reihe von browserbasierten Programmiersprachen wie JavaScript. Die Richtlinie ermöglicht es Skripten, die auf Seiten ausgeführt werden, die von derselben Site stammen, ohne besondere Einschränkungen auf die Methoden und Eigenschaften der anderen Site zuzugreifen, verhindert jedoch den Zugriff auf die meisten Methoden und Eigenschaften über Seiten auf verschiedenen Sites hinweg.

Damit Sie Daten abrufen können, müssen folgende sein:

Gleiches Protokoll und Host

Sie müssen JSONP implementieren, um dies zu umgehen.

Sarfraz
quelle
17

Ich musste die Webseite von der lokalen Festplatte "file: /// C: /test/htmlpage.html" laden, die URL "http: //localhost/getxml.php" aufrufen und dies in den Browsern IE8 + und Firefox12 + tun. Verwenden Sie jQuery v1 .7.2 lib zur Minimierung des Boilerplate-Codes. Nachdem ich Dutzende von Artikeln gelesen hatte, fand ich es endlich heraus. Hier ist meine Zusammenfassung.

  • Das Serverskript (.php, .jsp, ...) muss den http-Antwortheader zurückgeben. Access-Control-Allow-Origin: *
  • Setzen Sie vor der Verwendung von jQuery ajax dieses Flag in Javascript: jQuery.support.cors = true;
  • Sie können das Flag ein- oder jedes Mal setzen, bevor Sie die jQuery-Ajax-Funktion verwenden
  • Jetzt kann ich XML-Dokumente in IE und Firefox lesen. Andere Browser habe ich nicht getestet.
  • Das Antwortdokument kann Klartext / Text, XML, JSON oder etwas anderes sein

Hier ist ein Beispiel für einen jQuery-Ajax-Aufruf mit einigen Debug-Sysouts.

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);
    }
});
Wen
quelle
1
Ich habe hier eine Antwort auf diese Frage geschrieben: Das Laden einer domänenübergreifenden HTML-Seite mit jQuery AJAX - die letzte, unterstützt https
jherax
Für den sichersten Punkt: Fügen Sie in PHP diese Zeile zum Skript hinzu:header("Access-Control-Allow-Origin: *");
T30
1
@ wem vielen Dank für Ihre Antwort. Sie haben mir sehr geholfen. Prost.
Luis Milanese
10

Es ist richtig, dass die Richtlinie mit demselben Ursprung verhindert, dass JavaScript domänenübergreifende Anforderungen stellt. Die CORS-Spezifikation ermöglicht jedoch genau die Art von API-Zugriff, nach der Sie suchen, und wird von den aktuellen Hauptbrowsern unterstützt.

Informationen zum Aktivieren der gemeinsamen Nutzung von Ressourcen zwischen verschiedenen Ursprüngen für Client und Server:

http://enable-cors.org/

"Cross-Origin Resource Sharing (CORS) ist eine Spezifikation, die einen wirklich offenen Zugriff über Domänengrenzen hinweg ermöglicht. Wenn Sie öffentliche Inhalte bereitstellen, sollten Sie CORS verwenden, um sie für den universellen JavaScript- / Browserzugriff zu öffnen."

Jason
quelle
9

Ich benutze den Apache-Server, also habe ich das Modul mod_proxy verwendet. Module aktivieren:

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

Dann füge hinzu:

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

Übergeben Sie abschließend die Proxy-URL an Ihr Skript.

Zenio
quelle
8

Die Browsersicherheit verhindert, dass ein Ajax-Aufruf von einer in einer Domain gehosteten Seite zu einer in einer anderen Domain gehosteten Seite erfolgt. Dies wird als " Politik gleichen Ursprungs " bezeichnet.

Jacob Mattison
quelle
4

Aus den Jquery-Dokumenten ( Link ):

  • Aufgrund von Sicherheitsbeschränkungen des Browsers unterliegen die meisten "Ajax" -Anfragen derselben Ursprungsrichtlinie. Die Anforderung kann Daten aus einer anderen Domäne, Subdomäne oder einem anderen Protokoll nicht erfolgreich abrufen.

  • Skript- und JSONP-Anforderungen unterliegen nicht denselben Einschränkungen für Ursprungsrichtlinien.

Ich würde also davon ausgehen, dass Sie jsonp für die Anfrage verwenden müssen. Aber ich habe es nicht selbst versucht.

William Clemens
quelle
2

Ich kenne 3 Möglichkeiten, um Ihr Problem zu lösen:

  1. Wenn Sie Zugriff auf beide Domänen haben, können Sie zunächst den Zugriff für alle anderen Domänen zulassen, indem Sie:

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

    oder nur eine Domain durch Hinzufügen des folgenden Codes zur .htaccess-Datei:

    <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. Sie können eine Ajax-Anfrage an eine PHP-Datei auf Ihrem Server haben und die Anfrage an eine andere Domain mit dieser PHP-Datei bearbeiten.

  3. Sie können jsonp verwenden, da es keine Berechtigung benötigt. Hierzu kannst du die Antwort unseres Freundes @BGerrissen lesen.
Ali_Hr
quelle
0

Für Microsoft Azure ist das etwas anders.

Azure verfügt über eine spezielle CORS-Einstellung, die festgelegt werden muss. Hinter den Kulissen ist es im Wesentlichen dasselbe, aber das einfache Setzen des Headers, den Joshuarh erwähnt, funktioniert nicht. Die Azure-Dokumentation zum Aktivieren der domänenübergreifenden Aktivierung finden Sie hier:

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

Ich habe ein paar Stunden damit herumgespielt, bevor mir klar wurde, dass meine Hosting-Plattform diese spezielle Einstellung hat.

Josh Schultz
quelle
0

es funktioniert, alles was Sie brauchen:

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 Ajax):

var getWBody = $.ajax({ cache: false,
        url: URL,
        dataType : 'json',
        type: 'GET',
        xhrFields: { withCredentials: true }
});
Paun Narcis Iulian
quelle