XmlHttpRequest-Fehler: Origin null ist von Access-Control-Allow-Origin nicht zulässig

550

Ich entwickle eine Seite, die Bilder von Flickr und Panoramio über die AJAX-Unterstützung von jQuery abruft.

Die Flickr-Seite funktioniert einwandfrei, aber wenn ich es $.get(url, callback)von Panoramio aus versuche, wird in der Chrome-Konsole ein Fehler angezeigt:

XMLHttpRequest kann 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 nicht laden . Origin null ist von Access-Control-Allow-Origin nicht zulässig.

Wenn ich diese URL direkt von einem Browser abfrage, funktioniert es einwandfrei. Was ist los und kann ich das umgehen? Verfasse ich meine Abfrage falsch oder unternimmt Panoramio dies, um zu verhindern, dass ich versuche, dies zu tun?

Google hat in der Fehlermeldung keine nützlichen Übereinstimmungen gefunden .

BEARBEITEN

Hier ist ein Beispielcode, der das Problem zeigt:

$().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);
  });
});

Sie können das Beispiel online ausführen .

BEARBEITEN 2

Vielen Dank an Darin für seine Hilfe. Der obige Code ist falsch. Verwenden Sie stattdessen Folgendes:

$().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...
  });
});
Drew Noakes
quelle
1
Wie sieht die URL aussehen , dass Sie die Anfrage machen aus ? Dies ist nicht zufällig eine dynamisch generierte iframe, in die Sie document.writezum Beispiel?
Pekka
5
Können Sie die HTTP-Antwort von der Anfrage an jeden Dienst senden? Ich wette, Panoramio bietet Access-Control-Allow-Origin nicht an. Beispiele finden Sie unter w3.org/TR/cors .
Kevin Hakanson
2
@ Kevin, Sie brauchen diese Header nicht, wenn der Server JSONP sendet.
Darin Dimitrov
@ Pekka, ich führe die Seite gerade von meinem lokalen Computer aus ( file:///C:/). Nein iframeist beteiligt.
Drew Noakes
1
@ zog, was passiert, wenn Sie es von einer http-URL ausführen? Auf diese Weise sollte es keinen Unterschied machen, sondern nur die Möglichkeit ausschließen.
Pekka

Antworten:

423

Soweit ich das beurteilen kann, hatten Sie zwei Probleme:

  1. Sie haben Ihrem Typ keinen "jsonp" -Typbezeichner übergeben $.get, daher wurde ein gewöhnlicher XMLHttpRequest verwendet. Ihr Browser unterstützte jedoch CORS (Cross-Origin Resource Sharing), um domänenübergreifendes XMLHttpRequest zuzulassen, wenn der Server dies genehmigt hat. Hier kam der Access-Control-Allow-OriginHeader ins Spiel.

  2. Ich glaube, Sie haben erwähnt, dass Sie es von einer Datei aus ausführen: // URL. Es gibt zwei Möglichkeiten für CORS-Header, um zu signalisieren, dass eine domänenübergreifende XHR in Ordnung ist. Eine ist das Senden Access-Control-Allow-Origin: *(was, wenn Sie Flickr über $.geterreicht haben, das getan haben muss), während die andere den Inhalt des OriginHeaders zurücksendet. Allerdings file://produzieren URLs eine Null Origin, die nicht über echo zurück genehmigt werden.

Das erste Problem wurde auf Umwegen durch Darins Vorschlag gelöst $.getJSON. Es ist ein wenig magisch, den Anforderungstyp von "json" in "jsonp" zu ändern, wenn die Teilzeichenfolge callback=?in der URL angezeigt wird .

Dies löste das zweite Problem, indem nicht mehr versucht wurde, eine CORS-Anforderung über eine file://URL auszuführen .

Um dies für andere Personen zu verdeutlichen, finden Sie hier die einfachen Anweisungen zur Fehlerbehebung:

  1. Wenn Sie versuchen, JSONP zu verwenden, stellen Sie sicher, dass einer der folgenden Fälle der Fall ist:
    • Sie verwenden $.getund einstellen dataTypeauf jsonp.
    • Sie verwenden $.getJSONund sind callback=?in der URL enthalten.
  2. Wenn Sie versuchen, eine domänenübergreifende XMLHttpRequest über CORS durchzuführen ...
    1. Stellen Sie sicher, dass Sie über testen http://. Skripte, die über ausgeführt file://werden, unterstützen CORS nur eingeschränkt.
    2. Stellen Sie sicher, dass der Browser CORS tatsächlich unterstützt . (Opera und Internet Explorer kommen zu spät zur Party)
ssokolow
quelle
45
Was ist die Lösung dafür?
jQuerybeast
19
Rückruf =? FTW
Tim
10
Einige Browser wie Chrome erlauben CORS, wenn sie mit dem Parameter --allow-file-access-from-files
echox
1
callback=?hat bei mir nicht funktioniert, aber jsonp=?funktioniert. Irgendeine Erklärung dafür?
Crunkchitis
1
Muss ich einen Webserver installieren, um über zu testen http://? Oder gibt es eine Möglichkeit, die Datei einfach mit diesem Protokoll zu öffnen?
Will Sewell
76

Sie müssen vielleicht einen HEADER in Ihr aufgerufenes Skript einfügen. Folgendes musste ich in PHP tun:

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

Weitere Informationen finden Sie im domänenübergreifenden AJAX oder im WEB (auf Französisch).

Thomas Decaux
quelle
1
@Uri: Hängt von Ihrem HTTP-Server ab. Mit Apache möchten Sie sich mit mod_headers befassen.
ssokolow
4
@Uri <meta http-equiv = "Zugriffskontrolle-Zulassen-Ursprung" content = "*">
Herberth Amaral
7
@HerberthAmaral Ich habe versucht, dies in <head> </ head> hinzuzufügen, aber es funktioniert bei mir nicht. Ich versuche es in iOS Safari und Chrome, aber in der Konsole erhalte ich den Ursprung null, der durch den Fehler Access-Control-Allow-Origin nicht zulässig ist.
Thandasoru
3
Aus Sicherheitsgründen funktioniert es im Kopf der HTML-Datei nicht. Es muss ein Header sein. stackoverflow.com/questions/7015782/…
Justin Blank
Es kann nicht im HTML sein. Sie muss von dem Programm angegeben werden, das die HTML-Seite über das Netzwerk (sogenannter Webserver) an Ihren Browser sendet.
Roman Plášil
70

Für ein einfaches HTML-Projekt:

cd project
python -m SimpleHTTPServer 8000

Dann durchsuchen Sie Ihre Datei.

CodeGroover
quelle
1
während fantastisch und funktioniert, wenn Sie zu 0.0.0.0:8000 gehen und POSTAnfragen versuchen , die Sie erhalten: code 501, message Unsupported method ('POST')für die Brille.
pjammer
"Wenn ein Python-Webserver (wie z. B. cherrypy) angibt, dass er auf 0.0.0.0 bereitgestellt wird, bedeutet dies, dass er auf den gesamten TCP-Datenverkehr wartet, der auf diesem Computer landet, unabhängig vom angeforderten Hostnamen oder der angeforderten IP-Adresse." Versuchen Sie also vielleicht, auf localhost zu posten
eric.christensen
20

Funktioniert für mich unter Google Chrome v5.0.375.127 (ich erhalte die Benachrichtigung):

$.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);
});

Außerdem würde ich empfehlen, stattdessen die $.getJSON()Methode zu verwenden, da die vorherige unter IE8 (zumindest auf meinem Computer) nicht funktioniert:

$.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);
});

Sie können es versuchen online von hier aus .


AKTUALISIEREN:

Nachdem Sie Ihren Code angezeigt haben, kann ich das Problem damit erkennen. Sie haben sowohl eine anonyme Funktion als auch eine Inline-Funktion, aber beide werden aufgerufenprocessImages . So funktioniert die JSONP-Unterstützung von jQuery. Beachten Sie, wie ich das definiere, callback=?damit Sie eine anonyme Funktion verwenden können. Weitere Informationen finden Sie in der Dokumentation .

Eine andere Bemerkung ist, dass Sie eval nicht nennen sollten. Der an Ihre anonyme Funktion übergebene Parameter wird bereits von jQuery in JSON analysiert.

Darin Dimitrov
quelle
Hmm ok lass es mich nochmal versuchen. Ich bin auf einer anderen Version von Chrome übrigens "6.0.472.51 Beta".
Drew Noakes
Ihr Code hat bei mir funktioniert. Ich habe meine Frage mit einem Code aktualisiert, der das Problem aufzeigt.
Drew Noakes
Vielen Dank für den Tipp bezüglich getJSON ... Ich habe Ihr jsFiddle-Beispiel gegabelt, um das Problem zu zeigen ( jsfiddle.net/ZfvKm ), und jetzt wird die Fehlermeldung XMLHttpRequest
Drew Noakes
@Darin, danke für das Update. Ich verstehe Ihren Standpunkt und habe mit einigen Kombinationen davon gespielt, aber ich muss noch einen Weg finden, um auf das zurückgegebene Objekt zuzugreifen. Könnten Sie Ihr jsFiddle-Beispiel aktualisieren, um den Zugriff auf die Daten anzuzeigen? Wenn Sie den Rückruf auf setzen, ?wird der zurückgegebene JSON in Klammern gesetzt. Sie definieren keinen Parameter für Ihre Rückruffunktion, und der Wert von thisscheint kein Antwortobjekt zu haben (zumindest ist der .dataWert null).
Drew Noakes
@Darin, fantastisch. Danke vielmals. Funktioniert jetzt gut. Für alle anderen, die dies lesen, weist die Einbeziehung von callback=?jQuery an, intern einen zufälligen Funktionsnamen zu generieren, was zu einem Aufruf der anonymen Funktion führt, an die Sie übergeben .getJSON. Geschätzt.
Drew Noakes
8

Verwenden Sie die JSONP-Schnittstelle (JSON Padding), solange der angeforderte Server das JSON-Datenformat unterstützt. Sie können damit externe Domänenanforderungen ohne Proxyserver oder ausgefallene Header-Inhalte stellen.

Cheng Chen
quelle
5

Es ist dieselbe Ursprungsrichtlinie . Sie müssen eine JSON-P-Schnittstelle oder einen Proxy verwenden, der auf demselben Host ausgeführt wird.

QUentin
quelle
4

Wir haben es über die http.confDatei verwaltet (den HTTP-Dienst bearbeitet und dann neu gestartet):

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

In der Header set Access-Control-Allow-Origin "*"können Sie eine genaue URL eingeben.

romu31
quelle
1
Dies funktioniert nicht mit XAMPPs Apache. Das Problem besteht immer noch.
Raptor
1
Das ist unsicher. Sehen Sie hier warum; stackoverflow.com/questions/7564832/…
Rob
Es ist unsicher, wie @RobQuist sagte.
d337
4

Wenn Sie lokale Tests durchführen oder die Datei von so etwas wie aufrufen file:// , müssen Sie die Browsersicherheit deaktivieren.

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

user2701060
quelle
3

In meinem Fall funktionierte derselbe Code in Firefox einwandfrei, jedoch nicht in Google Chrome. In der JavaScript-Konsole von Google Chrome heißt es:

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"

Ich musste den WWW-Teil der Ajax-URL löschen, damit er korrekt mit der Ursprungs-URL übereinstimmt, und dann funktionierte er einwandfrei.

Kalpesh Patel
quelle
2

Nicht alle Server unterstützen jsonp. Der Server muss die Rückruffunktion in den Ergebnissen festlegen. Ich verwende dies, um JSON-Antworten von Websites zu erhalten, die reines JSON zurückgeben, aber JSONP nicht unterstützen:

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;
    });
}
mAsT3RpEE
quelle
1

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
1

Als letzte Anmerkung der sagt Mozilla Dokumentation ausdrücklich , dass

Das obige Beispiel würde fehlschlagen, wenn der Header mit einem Platzhalter versehen wäre: Access-Control-Allow-Origin: *. Da in Access-Control-Allow-Origin http: //foo.example explizit erwähnt wird , wird der Inhalt mit Anmeldeinformationen an den aufrufenden Webinhalt zurückgegeben.

Infolgedessen ist es nicht einfach eine schlechte Praxis, '*' zu verwenden. Funktioniert einfach nicht :)

user2688838
quelle
1

Für PHP - das funktioniert für mich auf Chrome, Safari und Firefox

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

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

mit axios call php live services mit datei: //

Tyler
quelle
Dies funktioniert auch bei mir. Beachten Sie, dass null ein STRING und kein tatsächlicher NULL ist. Ich benutze es header('Access-Control-Allow-Origin: '.( trim($_SERVER['HTTP_REFERER'],'/') ?:'null'),true);, um den Cross-Origin von einem Remote-Server zu einem anderen zu ermöglichen und für die lokale Datei auf (string) null zu fallen.
Louis Loudog Trottier
0

Ich habe auch den gleichen Fehler in Chrome erhalten (ich habe andere Browser nicht getestet). Es lag an der Tatsache, dass ich auf domain.com anstatt auf www.domain.com navigierte. Ein bisschen seltsam, aber ich könnte das Problem lösen, indem ich die folgenden Zeilen zu .htaccess hinzufüge. Domain.com wird auf www.domain.com umgeleitet und das Problem wurde behoben. Ich bin ein fauler Webbesucher, daher schreibe ich fast nie das WWW, aber anscheinend ist es in einigen Fällen erforderlich.

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

Stellen Sie sicher, dass Sie die neueste Version von JQuery verwenden. Wir hatten diesen Fehler für JQuery 1.10.2 und der Fehler wurde nach Verwendung von JQuery 1.11.1 behoben

Ganesh Kamath - "Code Frenzy"
quelle
0

Leute,

Ich bin auf ein ähnliches Problem gestoßen. Aber mit Fiddler konnte ich das Problem lösen. Das Problem besteht darin, dass die Client-URL, die in der CORS-Implementierung auf der Web-API-Seite konfiguriert ist, keinen abschließenden Schrägstrich enthalten darf. Nachdem Sie Ihre Anfrage über Google Chrome gesendet haben, überprüfen Sie die Textview - Registerkarte des Headers besagt Abschnitt von Fiddler, die Fehlermeldung etwas wie folgt aus :

* "Der angegebene Richtlinienursprung your_client_url: / 'ist ungültig. Er kann nicht mit einem Schrägstrich enden."

Das ist wirklich eigenartig, weil es im Internet Explorer ohne Probleme funktioniert hat, aber mir beim Testen mit Google Chrome Kopfschmerzen bereitet hat.

Ich habe den Schrägstrich im CORS-Code entfernt und die Web-API neu kompiliert. Jetzt ist die API ohne Probleme über Chrome und Internet Explorer zugänglich. Bitte probieren Sie es aus.

Danke, Andy

andymenon
quelle
0

In der von CodeGroover oben veröffentlichten Lösung gibt es ein kleines Problem: Wenn Sie eine Datei ändern, müssen Sie den Server neu starten, um die aktualisierte Datei tatsächlich zu verwenden (zumindest in meinem Fall).

Also habe ich ein bisschen gesucht und dieses gefunden. Zu verwenden:

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

Und dann wird es bei dienen http://localhost:8000.

MiJyn
quelle
1
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Von der Überprüfung
Vi100
Link geklärt.
MiJyn