XMLHttpRequest kann XXX nicht laden. Kein 'Access-Control-Allow-Origin'-Header

111

tl; dr; Informationen zur Richtlinie für denselben Ursprung

Ich habe einen Grunt-Prozess, der eine Instanz von express.js Server initiiert. Dies funktionierte bis jetzt absolut einwandfrei, als eine leere Seite mit dem folgenden Fehler im Fehlerprotokoll in der Entwicklerkonsole in Chrome (neueste Version) angezeigt wurde:

XMLHttpRequest kann https://www.example.com/ nicht laden. In der angeforderten Ressource ist kein Header 'Access-Control-Allow-Origin' vorhanden. Origin ' http: // localhost: 4300 ' ist daher kein Zugriff gestattet.

Was hindert mich daran, auf die Seite zuzugreifen?

Peter David Carter
quelle
Ich arbeite an der Website und es war gut vor fünf Minuten.
Peter David Carter
1
Gibt es CORS-Header aus? Vielleicht wäre es einfacher zu sehen, wenn Sie Code teilen würden
Jaromanda X
Plausibel. Welche Abteilung soll ich fragen, um es herauszufinden? Ich mache meistens nur das Backbone.marionette-Zeug ...
Peter David Carter
Ja. Ich nehme an, die Organisation der Abteilungen ist sowieso nicht immer einheitlich, daher ist es möglicherweise eine nebulöse Frage, aber ich würde gerne etwas über das Backend / Routing / Sys-Admin-Zeug in meinem Unternehmen erfahren, und dies schien eine gute Ausrede zu sein, um sich damit vertraut zu machen Ich selbst, wenn es in Zukunft Probleme gibt, kann ich helfen.
Peter David Carter
Ich würde jemanden auf der Serverseite in Ihrem Betrieb fragen. Sie müssen es an Ihnen geändert haben, wenn Sie zuvor darauf zugreifen konnten.
Larry Lane

Antworten:

203

tl; dr - Am Ende finden Sie eine Zusammenfassung und Überschriften in der Antwort, um das Auffinden der relevanten Teile zu erleichtern. Es wird jedoch empfohlen, alles zu lesen, da es nützliche Hintergrundinformationen zum Verständnis des Warum bietet , wodurch es einfacher wird, zu sehen, wie das Wie unter verschiedenen Umständen angewendet wird.

Informationen zur Richtlinie für denselben Ursprung

Dies ist das gleiche Ursprungsrichtlinie . Es ist eine Sicherheitsfunktion, die von Browsern implementiert wird.

Ihr spezieller Fall zeigt, wie es für XMLHttpRequest implementiert ist (und Sie erhalten identische Ergebnisse, wenn Sie fetch verwenden), aber es gilt auch für andere Dinge (wie Bilder, die auf a geladen werden) <canvas> oder in ein geladenes Dokument geladen werden <iframe>), nur mit leicht unterschiedliche Implementierungen.

(Seltsamerweise gilt dies auch für CSS-Schriftarten, aber das liegt daran, dass Found Foundries auf DRM bestanden und nicht auf den Sicherheitsproblemen, die in der Same Origin Policy normalerweise behandelt werden.)

Das Standardszenario, das die Notwendigkeit der SOP demonstriert, kann mit drei Zeichen demonstriert werden :

  • Alice ist eine Person mit einem Webbrowser
  • Bob betreibt eine Website ( https://www.[website].com/in Ihrem Beispiel)
  • Mallory betreibt eine Website ( http://localhost:4300in Ihrem Beispiel)

Alice ist bei Bob angemeldet und hat dort einige vertrauliche Daten. Möglicherweise handelt es sich um ein Unternehmens-Intranet (nur für Browser im LAN verfügbar) oder um ihr Online-Banking (nur mit einem Cookie verfügbar, das Sie nach Eingabe eines Benutzernamens und eines Kennworts erhalten).

Alice besucht Mallorys Website mit JavaScript, wodurch Alices Browser eine HTTP-Anfrage an Bobs Website sendet (von ihrer IP-Adresse mit ihren Cookies usw.). Dies kann so einfach sein wie das Verwenden XMLHttpRequestund Lesen desresponseText .

Die Same Origin-Richtlinie des Browsers verhindert, dass JavaScript die von Bobs Website zurückgegebenen Daten liest (auf die Mallory von Bob und Alice nicht zugreifen soll). (Beachten Sie, dass Sie zum Beispiel ein Bild anzuzeigen unter Verwendung eines <img>Elements über Herkunft , weil der Inhalt des Bildes nicht auf JavaScript (oder Mallory) ausgesetzt ist ... es sei denn , Sie Leinwand in die Waagschale werfen , in dem Fall , dass Sie wird erzeugen ein gleich Herkunft Verstoßfehler).


Warum die Richtlinie für denselben Ursprung gilt, wenn Sie nicht der Meinung sind, dass dies der Fall sein sollte

Für eine bestimmte URL ist es möglich, dass die SOP nicht benötigt wird. Einige gängige Szenarien, in denen dies der Fall ist, sind:

  • Alice, Bob und Mallory sind dieselbe Person.
  • Bob stellt vollständig öffentliche Informationen zur Verfügung

… Aber der Browser kann nicht wissen, ob eine der oben genannten Aussagen zutrifft. Daher erfolgt das Vertrauen nicht automatisch und die SOP wird angewendet. Die Erlaubnis muss ausdrücklich erteilt werden, bevor der Browser die Daten, die er erhalten hat, an eine andere Website weitergibt.


Warum die Richtlinie für denselben Ursprung nur für JavaScript auf einer Webseite gilt

Browsererweiterungen *, die Registerkarte Netzwerk in Browser-Entwicklertools und Anwendungen wie Postman sind installierte Software. Sie geben keine Daten von einer Website an das JavaScript einer anderen Website weiter, nur weil Sie diese andere Website besucht haben . Die Installation von Software erfolgt normalerweise bewusster.

Es gibt keinen Dritten (Mallory), der als Risiko eingestuft wird.

*Browser-Erweiterungen müssen sorgfältig geschrieben werden, um Probleme zwischen verschiedenen Ursprüngen zu vermeiden. Siehe zum Beispiel die Chrome-Dokumentation .


Warum Sie Daten auf der Seite anzeigen können, ohne sie mit JS zu lesen

Es gibt eine Reihe von Umständen, unter denen Mallorys Website dazu führen kann, dass ein Browser Daten von einem Drittanbieter abruft und anzeigt (z. B. durch Hinzufügen eines <img>Elements zum Anzeigen eines Bildes). Es ist Mallorys JavaScript jedoch nicht möglich, die Daten in dieser Ressource zu lesen. Dies können nur Alices Browser und Bobs Server. Daher ist es immer noch sicher.


CORS

Der Access-Control-Allow-OriginHTTP - Antwort - Header bezeichnete in der Fehlermeldung ist Teil des CORS - Standard, den Bob Erlaubnis Mallorys Website ausdrücklich erteilen , die Daten über Alices Browser zugreifen kann.

Eine grundlegende Implementierung würde nur Folgendes umfassen:

Access-Control-Allow-Origin: *

… In den Antwort-Headern, damit jede Website die Daten lesen kann.

Access-Control-Allow-Origin: http://example.com/

… Würde nur einer bestimmten Site den Zugriff darauf ermöglichen, und Bob kann diese basierend auf dem Origin Anforderungsheader dynamisch generieren, um mehreren, aber nicht allen Sites den Zugriff darauf zu ermöglichen.

Die Einzelheiten, wie Bob diesen Antwortheader festlegt, hängen vom HTTP-Server und / oder der serverseitigen Programmiersprache von Bob ab. Es gibt eine Sammlung von Handbüchern für verschiedene gängige Konfigurationen , die hilfreich sein können.

Modell, wo CORS-Regeln angewendet werden

NB: Einige Anforderungen sind komplex und senden eine Preflight- OPTIONS-Anforderung, auf die der Server antworten muss, bevor der Browser die GET / POST / PUT / Whatever-Anforderung sendet, die der JS stellen möchte. Implementierungen von CORS, die nur Access-Control-Allow-Originzu bestimmten URLs hinzugefügt werden , werden häufig dadurch ausgelöst.


Offensichtlich würde Bob die Erlaubnis nur über CORS erteilen, wenn entweder:

  • Die Daten waren nicht privat oder
  • Mallory wurde vertraut

Aber ich bin nicht Bob!

Es gibt keinen Standardmechanismus für Mallory , um diesen Header hinzuzufügen, da er von Bobs Website stammen muss, die sie nicht kontrolliert.

Wenn Bob eine öffentliche API ausführt, gibt es möglicherweise einen Mechanismus zum Aktivieren von CORS (möglicherweise durch Formatieren der Anforderung auf eine bestimmte Weise oder eine Konfigurationsoption nach dem Anmelden bei einer Developer Portal-Site für Bobs Site). Dies muss jedoch ein von Bob implementierter Mechanismus sein. Mallory könnte die Dokumentation auf Bobs Website lesen, um zu sehen, ob etwas verfügbar ist, oder sie könnte mit Bob sprechen und ihn bitten, CORS zu implementieren.


Fehlermeldungen mit der Angabe "Antwort für Preflight"

Einige Cross-Origin-Anfragen werden vorab geflogen .

Dies geschieht, wenn Sie (grob gesagt) versuchen, eine originensübergreifende Anfrage zu stellen, die:

  • Enthält Anmeldeinformationen wie Cookies
  • Konnte nicht mit einem normalen HTML-Formular generiert werden (z. B. mit benutzerdefinierten Headern oder einem Inhaltstyp, den Sie in einem Formular nicht verwenden konnten enctype).

Wenn Sie etwas richtig machen, das einen Preflight benötigt

In diesen Fällen dann der Rest dieser Antwort gilt nach wie vor , aber sie auch sicherstellen müssen , dass der Server für die Preflight - Anfrage hören kann (was sein OPTIONS(und nicht GET, POSToder was auch immer Sie senden versuchten) und reagieren auf sie mit der rechten Access-Control-Allow-OriginHeader aber auch Access-Control-Allow-Methodsund Access-Control-Allow-Headersum Ihre spezifischen HTTP-Methoden oder Header zuzulassen.

Wenn Sie versehentlich einen Preflight auslösen

Manchmal machen die Leute Fehler, wenn sie versuchen, Ajax-Anfragen zu erstellen, und manchmal lösen diese die Notwendigkeit eines Preflights aus. Wenn die API Ursprungsübergreifende Anforderungen zulässt, jedoch nichts erfordert, was einen Preflight erfordern würde, kann dies den Zugriff unterbrechen.

Häufige Fehler, die dies auslösen, sind:

  • versuchen, Access-Control-Allow-Originund andere CORS-Antwortheader auf die Anfrage zu setzen. Diese gehören nicht zur Anfrage, tun nichts Hilfreiches (was wäre der Punkt eines Berechtigungssystems, an dem Sie sich selbst die Erlaubnis erteilen könnten?) Und dürfen nur in der Antwort erscheinen.
  • Es wird versucht, einen Content-Type: application/jsonHeader auf eine GET-Anforderung zu setzen, die keinen Anforderungshauptteil hat, um den Inhalt von zu beschreiben (normalerweise, wenn der Autor Content-Typeund verwirrt Accept).

In beiden Fällen reicht das Entfernen des zusätzlichen Anforderungsheaders häufig aus, um die Notwendigkeit eines Preflights zu vermeiden (wodurch das Problem bei der Kommunikation mit APIs gelöst wird, die einfache Anforderungen, jedoch keine Preflight-Anforderungen unterstützen).


Undurchsichtige Antworten

Manchmal müssen Sie eine HTTP-Anfrage stellen, aber Sie müssen die Antwort nicht lesen. Beispiel, wenn Sie eine Protokollnachricht zur Aufzeichnung an den Server senden.

Wenn Sie die fetchAPI verwenden (anstatt XMLHttpRequest), können Sie sie so konfigurieren, dass sie nicht versucht, CORS zu verwenden.

Beachten Sie, dass Sie damit nichts tun können, was CORS tun muss. Sie können die Antwort nicht lesen. Sie können keine Anfrage stellen, für die ein Preflight erforderlich ist.

Sie können eine einfache Anfrage stellen, die Antwort nicht sehen und die Entwicklerkonsole nicht mit Fehlermeldungen füllen.

Wie das geht, wird in der Chrome-Fehlermeldung erläutert, die angezeigt wird, wenn Sie eine Anfrage mit stellen fetchund keine Berechtigung zum Anzeigen der Antwort mit CORS erhalten:

Der Zugriff auf das Abrufen von " https://example.com/vom Ursprung" https://example.netwurde durch die CORS-Richtlinie blockiert: In Access-Control-Allow-Originder angeforderten Ressource ist kein " " Header vorhanden. Wenn eine undurchsichtige Antwort Ihren Anforderungen entspricht, setzen Sie den Anforderungsmodus auf "no-cors", um die Ressource mit deaktiviertem CORS abzurufen.

So:

fetch("http://example.com", { mode: "no-cors" });

Alternativen zu CORS

JSONP

Bob könnte die Daten auch mithilfe eines Hacks wie JSONP bereitstellen. Auf diese Weise haben die Leute Ajax übergreifend hergestellt, bevor CORS hinzukam.

Es funktioniert, indem die Daten in Form eines JavaScript-Programms dargestellt werden, das die Daten in Mallorys Seite einfügt.

Es erfordert, dass Mallory Bob vertraut, um keinen schädlichen Code bereitzustellen.

Beachten Sie das allgemeine Thema: Die Site, die die Daten bereitstellt, muss dem Browser mitteilen, dass es für eine Site eines Drittanbieters in Ordnung ist, auf die Daten zuzugreifen, die sie an den Browser sendet.

Da JSONP ein <script>Element anfügt , um die Daten in Form eines JavaScript-Programms zu laden, das eine bereits auf der Seite vorhandene Funktion aufruft, schlägt der Versuch, die JSONP-Technik für eine URL zu verwenden, die JSON zurückgibt, fehl - normalerweise mit einem CORB-Fehler - aufgrund von JSON ist kein JavaScript.

Verschieben Sie die beiden Ressourcen zu einem einzigen Ursprung

Wenn sich das HTML-Dokument, in dem der JS ausgeführt wird, und die angeforderte URL auf demselben Ursprung befinden (dasselbe Schema, denselben Hostnamen und denselben Port verwenden), erteilt die Richtlinie für denselben Ursprung standardmäßig die Berechtigung. CORS wird nicht benötigt.

Ein Proxy

Mallory konnte serverseitigen Code verwenden, um die Daten abzurufen (die sie dann wie gewohnt über HTTP von ihrem Server an Alices Browser weiterleiten konnte).

Es wird entweder:

  • CORS-Header hinzufügen
  • Konvertieren Sie die Antwort in JSONP
  • existieren auf demselben Ursprung wie das HTML-Dokument

Dieser serverseitige Code kann von einem Dritten (z. B. CORS Anywhere) geschrieben und gehostet werden. Beachten Sie die Auswirkungen auf den Datenschutz: Der Dritte kann überwachen, wer was auf seinen Servern vertritt.

Bob würde dafür keine Berechtigungen erteilen müssen.

Hier gibt es keine Auswirkungen auf die Sicherheit, da dies nur zwischen Mallory und Bob liegt. Es gibt für Bob keine Möglichkeit zu glauben, dass Mallory Alice ist, und Mallory Daten zur Verfügung zu stellen, die zwischen Alice und Bob vertraulich behandelt werden sollten.

Folglich kann Mallory diese Technik nur zum Lesen öffentlicher Daten verwenden.

Beachten Sie jedoch, dass das Entnehmen von Inhalten von der Website einer anderen Person und deren Anzeige auf eigene Faust eine Verletzung des Urheberrechts darstellen und Sie für rechtliche Schritte öffnen kann.

Etwas anderes als eine Web-App schreiben

Wie im Abschnitt "Warum die gleiche Ursprungsrichtlinie nur für JavaScript auf einer Webseite gilt" erwähnt, können Sie die SOP vermeiden, indem Sie kein JavaScript auf einer Webseite schreiben.

Das bedeutet nicht, dass Sie JavaScript und HTML nicht weiter verwenden können, aber Sie können es mithilfe eines anderen Mechanismus wie Node-WebKit oder PhoneGap verteilen.

Browser-Erweiterungen

Es ist möglich, dass eine Browsererweiterung die CORS-Header in die Antwort einfügt, bevor die Richtlinie für denselben Ursprung angewendet wird.

Diese können für die Entwicklung nützlich sein, sind jedoch für eine Produktionssite nicht praktikabel (es ist unangemessen, jeden Benutzer Ihrer Site zu bitten, eine Browsererweiterung zu installieren, die eine Sicherheitsfunktion seines Browsers deaktiviert).

Sie funktionieren auch in der Regel nur mit einfachen Anforderungen (Fehler bei der Bearbeitung von Preflight-OPTIONS-Anforderungen).

Eine richtige Entwicklungsumgebung mit einem lokalen Entwicklungs Mit Server ist in der Regel ein besserer Ansatz.


Sonstige Sicherheitsrisiken

Beachten Sie, dass SOP / CORS keine XSS- , CSRF- oder SQL Injection- Angriffe abschwächt , die unabhängig voneinander behandelt werden müssen.


Zusammenfassung

  • In Ihrem clientseitigen Code können Sie nichts tun , was den CORS-Zugriff auf den Server eines anderen ermöglicht .
  • Wenn Sie den Server steuern, wird folgende Anforderung gestellt: Fügen Sie CORS-Berechtigungen hinzu.
  • Wenn Sie mit der Person, die es kontrolliert, befreundet sind: Lassen Sie sie CORS-Berechtigungen hinzufügen.
  • Wenn es ein öffentlicher Dienst ist:
    • Lesen Sie die API-Dokumentation, um zu erfahren, was sie über den Zugriff mit clientseitigem JavaScript sagen:
      • Sie werden möglicherweise aufgefordert, bestimmte URLs zu verwenden
      • Sie könnten JSONP unterstützen
      • Sie unterstützen möglicherweise überhaupt keinen Cross-Origin-Zugriff über clientseitigen Code (dies kann aus Sicherheitsgründen eine bewusste Entscheidung sein, insbesondere wenn Sie bei jeder Anforderung einen personalisierten API-Schlüssel übergeben müssen).
    • Stellen Sie sicher, dass Sie keine Preflight-Anfrage auslösen, die Sie nicht benötigen. Die API gewährt möglicherweise Berechtigungen für einfache Anforderungen, jedoch nicht für vorab geflogene Anforderungen.
  • Wenn keine der oben genannten Bedingungen zutrifft: Lassen Sie den Browser stattdessen mit Ihrem Server kommunizieren, und lassen Sie dann die Daten vom anderen Server abrufen und weiterleiten. (Es gibt auch gehostete Dienste von Drittanbietern, die CORS-Header an öffentlich zugängliche Ressourcen anhängen, die Sie verwenden können.)
QUentin
quelle
Wenn ich ein lokales LAN auf einem Webserver betreibe und versuche, Ajax von der IP / URL zu laden, funktioniert das? Das habe ich noch nicht versucht. als mein Webserver, der json-Daten speichert, wäre eine MCU
Ciasto piekarz
@Ciastopiekarz - Es gelten normale Regeln für denselben Ursprung / unterschiedliche Herkunft. Es gelten die normalen Netzwerkroutingregeln.
Quentin
25
Die vollständigste Antwort, die ich je gelesen habe, anstatt nur einen Link über Kors.
Pungggi
@ Quentin - Wow! +1! Wenn Alice die CORS-Erweiterung verwendet, ist der Server der Ansicht, dass ihre http-Aufrufe nicht aus Javascript, sondern aus einer Browser-Erweiterung stammen, und behandelt sie wie eine normale Anfrage mit demselben Ursprung.
Snippetkid
@snippetkid - Nein. Im Normalfall sendet der Server CORS-Header als Antwort und es ist ihm egal, woher die Anfrage stammt. Es liegt in der Verantwortung des Browsers, den Zugriff auf die Daten für den JS basierend auf den CORS-Headern in der Antwort zuzulassen oder zu verweigern. (Die Dinge werden auf dem Server / wenig / komplexer, wenn es um Preflight-Anfragen geht)
Quentin
3

Der Zielserver muss eine originensübergreifende Anforderung zulassen. Um dies durch Express zu ermöglichen, bearbeiten Sie einfach die http-Optionsanforderung:

app.options('/url...', function(req, res, next){
   res.header('Access-Control-Allow-Origin', "*");
   res.header('Access-Control-Allow-Methods', 'POST');
   res.header("Access-Control-Allow-Headers", "accept, content-type");
   res.header("Access-Control-Max-Age", "1728000");
   return res.sendStatus(200);
});
Daphoque
quelle
3

Da dies in der akzeptierten Antwort nicht erwähnt wird.

  • Dies ist bei genau dieser Frage nicht der Fall, kann aber anderen helfen, die nach diesem Problem suchen
  • Dies können Sie in Ihrem Client-Code tun, um in einigen Fällen CORS-Fehler zu vermeiden .

Sie können einfache Anfragen verwenden .
Um 'Einfache Anfragen' auszuführen, muss die Anfrage mehrere Bedingungen erfüllen. Zum Beispiel erlaubt nur POST, GETund HEADVerfahren, sowie nur einige bestimmte Header ermöglicht (Sie alle Bedingungen finden hier ).

Wenn Ihr Client - Code nicht explizit Satz nicht betroffen Header (zB „Accept“) mit einem festen Wert in der Anforderung es könnte vorkommen , dass einige Kunden akzeptieren setzen Sie diese Header automatisch mit einigen „Nicht-Standard“ Werte verursachen den Server nicht als Einfache Anfrage - die Ihnen einen CORS-Fehler gibt.

zwif
quelle
2

Dies geschieht aufgrund des CORS-Fehlers. CORS steht für Cross Origin Resource Sharing. Mit einfachen Worten, dieser Fehler tritt auf, wenn wir versuchen, von einer anderen Domäne aus auf eine Domäne / Ressource zuzugreifen.

Lesen Sie hier mehr darüber: CORS-Fehler mit jquery

Um dies zu beheben, müssen Sie, wenn Sie Zugriff auf die andere Domäne haben, Access-Control-Allow-Origin auf dem Server zulassen. Dies kann in den Headern hinzugefügt werden. Sie können dies für alle Anforderungen / Domänen oder eine bestimmte Domäne aktivieren.

So funktioniert eine CORS-Post-Anfrage (Cross-Origin Resource Sharing)

Diese Links können helfen

Vishnu
quelle
0

Dieses CORS-Problem wurde (aus anderen Gründen) nicht weiter ausgeführt.

Ich habe dieses Problem derzeit aus einem anderen Grund. Mein Frontend gibt auch den Header-Fehler 'Access-Control-Allow-Origin' zurück.

Nur, dass ich auf die falsche URL verwiesen habe, sodass dieser Header nicht richtig wiedergegeben wurde (in dem ich immer davon ausgegangen bin). localhost (Front-End) -> Aufruf von nicht gesichertem http (angeblich https). Stellen Sie sicher, dass der API-Endpunkt vom Front-End auf das richtige Protokoll zeigt.

morph85
quelle
0

Ich habe den gleichen Fehler in der Chrome-Konsole erhalten.

Mein Problem war, ich habe versucht, mit http://statt auf die Website zu gehen https://. Es gab also nichts zu reparieren, sondern musste nur mit auf dieselbe Site gehen https.

Subhashi
quelle
-1

Die Anforderung "Get" mit anhängenden Headern wird in die Anforderung "Options" umgewandelt. Es treten also Cors-Richtlinienprobleme auf. Sie müssen die Anforderung "Optionen" auf Ihrem Server implementieren.

kira
quelle
-6

Sie sollten CORS aktivieren, damit es funktioniert.

Perostek Balveda
quelle