it-swarm.com.de

XMLHttpRequest kann keinen XXX-Header "Access-Control-Allow-Origin" laden

tl; dr; Über dieselbe Origin-Richtlinie

Ich habe einen Grunt-Prozess, der eine Instanz des express.js-Servers initiiert. Dies funktionierte absolut einwandfrei, bis vor kurzem eine leere Seite mit folgenden Informationen im Fehlerprotokoll in der Entwicklerkonsole in Chrome (neueste Version) angezeigt wurde:

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

Was hindert mich daran, auf die Seite zuzugreifen?

63

tl; dr - Es gibt eine Zusammenfassung am Ende und Überschriften in der Antwort, um das Auffinden der relevanten Teile zu erleichtern. Es wird jedoch empfohlen, alles zu lesen, da dies einen nützlichen Hintergrund für das Verständnis des Warum bietet, um zu sehen, wie das Wie gilt unter anderen Umständen leichter.

Über die gleiche Ursprungsrichtlinie

Dies ist die Same Origin Policy . Dies 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 einen <canvas> Oder Dokumente geladen sind) in einen <iframe>), nur mit etwas anderen Implementierungen.

(Seltsamerweise gilt dies auch für CSS-Schriftarten. Dies liegt jedoch daran, dass die Hersteller auf DRM bestanden und nicht auf den Sicherheitsaspekten, die in der Regel in der Richtlinie von Same Origin behandelt werden.).

Das Standardszenario, das die Notwendigkeit von 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:4300 In Ihrem Beispiel)

Alice ist auf Bobs Website eingeloggt und hat dort einige vertrauliche Daten. Vielleicht ist es ein Firmen-Intranet (nur für Browser im LAN zugänglich) oder ihr Online-Banking (nur mit einem Cookie, das Sie nach Eingabe eines Benutzernamens und eines Passworts erhalten).

Alice besucht Mallorys Website, die über JavaScript verfügt, wodurch Alices Browser eine HTTP-Anfrage an Bobs Website sendet (von ihrer IP-Adresse mit ihren Cookies usw.). Dies kann so einfach sein, dass Sie XMLHttpRequest verwenden und responseText lesen.

Die Same Origin Policy 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 beispielsweise ein Bild mit einem <img> - Element über die Ursprünge hinweg anzeigen können, da der Inhalt des Bildes nicht JavaScript (oder Mallory) ausgesetzt ist. In diesem Fall müssen Sie jedoch die Leinwand in den Mix werfen wird einen Verstoß gegen denselben Ursprung erzeugen).


Warum die Richtlinie für denselben Ursprung gilt, wenn Sie dies nicht für erforderlich halten

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

  • Alice, Bob und Mallory sind die gleiche Person.
  • Bob informiert vollständig öffentlich

… Aber der Browser kann nicht erkennen, ob eine der oben genannten Aussagen zutrifft. Daher erfolgt keine automatische Vertrauensstellung und die SOP) wird angewendet. Die Erlaubnis muss explizit erteilt werden, bevor der Browser die Daten weitergibt es wurde auf eine andere Website gegeben.


Warum gilt die Richtlinie von Same Origin nur für JavaScript auf einer Webseite?

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 ist in der Regel bewusster.

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


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 Dritten abruft und anzeigt (z. B. durch Hinzufügen eines <img> - Elements zur Anzeige eines Bildes). Es ist jedoch nicht möglich, dass Mallorys JavaScript die Daten in dieser Ressource liest. Nur Alices Browser und Bobs Server können dies, sodass es immer noch sicher ist.


CORS

Der Access-Control-Allow-Origin - Header, auf den in der Fehlermeldung verwiesen wird, ist Teil des Standards CORS , mit dem Bob Mallory explizit die Berechtigung zum Zugriff auf die Website erteilen kann Daten über Alices Browser.

Eine grundlegende Implementierung würde nur Folgendes umfassen:

Access-Control-Allow-Origin: *

… Damit jede Website die Daten lesen kann.

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

… Würde es nur einer bestimmten Site erlauben, darauf zuzugreifen, und Bob kann dies basierend auf dem Origin request -Header dynamisch generieren, damit mehrere, aber nicht alle Sites darauf zugreifen können.

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 Anleitungen für verschiedene gängige Konfigurationen das könnte hilfreich sein.

Model of where CORS rules are applied

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


Offensichtlich würde Bob die Genehmigung über CORS nur dann erteilen, wenn:

  • 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 allerdings 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, die "Response for Preflight" erwähnen

Einige Cross Origin-Anfragen sind Preflight .

Dies passiert (grob gesagt), wenn Sie versuchen, eine Cross-Origin-Anfrage zu stellen, die:

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

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

In diesen Fällen gilt dann der Rest dieser Antwort weiterhin , Sie müssen jedoch auch sicherstellen, dass der Server auf die Preflight-Anforderung warten kann (dies ist OPTIONS (und nicht GET, POST oder was auch immer Sie senden wollten) und antworten Sie darauf mit dem richtigen Access-Control-Allow-Origin - Header, sondern auch mit Access-Control-Allow-Methods und Access-Control-Allow-Headers, um 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 konstruieren, und manchmal lösen sie die Notwendigkeit eines Preflight aus. Wenn die API so konzipiert ist, dass sie herkunftsübergreifende Anforderungen zulässt, jedoch keine Preflight-Prüfung erfordert, kann dies den Zugriff unterbrechen.

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

  • versucht, Access-Control-Allow-Origin und andere CORS-Antwortheader in die Anforderung einzufügen. Diese gehören nicht zur Anfrage, tun nichts Hilfreiches (was wäre der Sinn eines Berechtigungssystems, bei dem Sie sich selbst die Berechtigung erteilen könnten?) Und dürfen nur in der Antwort erscheinen.
  • es wird versucht, einen Content-Type: application/json - Header in eine GET-Anforderung einzufügen, der keinen Anforderungshauptteil zur Beschreibung des Inhalts enthält (normalerweise, wenn der Autor Content-Type und Accept verwechselt).

In beiden Fällen reicht das Entfernen des zusätzlichen Anforderungsheaders häufig aus, um die Notwendigkeit eines Preflight zu vermeiden (wodurch das Problem bei der Kommunikation mit APIs behoben 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. z.B. Wenn Sie eine Protokollnachricht zur Aufzeichnung auf dem Server veröffentlichen.

Wenn Sie die API fetch (anstelle von XMLHttpRequest) verwenden, können Sie es so konfigurieren, dass es 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 Anforderung stellen, für die ein Preflight erforderlich ist.

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

Die Vorgehensweise wird durch die Fehlermeldung Chrome) erläutert, die angezeigt wird, wenn Sie eine Anfrage mit fetch stellen und keine Berechtigung zum Anzeigen der Antwort mit CORS erhalten:

Der Zugriff auf den Abruf von 'https://example.com/' Von Origin 'https://example.net' Wurde durch die CORS-Richtlinie blockiert: In der angeforderten Ressource ist kein 'Access-Control-Allow-Origin' - Header vorhanden. Wenn eine undurchsichtige Antwort Ihren Anforderungen entspricht, setzen Sie den Anforderungsmodus auf "no-cors", um die Ressource bei deaktiviertem CORS abzurufen.

Somit:

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

Alternativen zu CORS

JSONP

Bob könnte die Daten auch mit einem Hack wie JSONP bereitstellen. Auf diese Weise haben die Leute Origin Ajax überquert, bevor CORS dazukam.

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

Mallory muss darauf vertrauen, dass Bob keinen bösartigen Code bereitstellt.

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 an den Browser gesendet werden.

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, in der Regel mit fehl Ein CORB-Fehler, da JSON kein JavaScript ist.

Verschieben Sie die beiden Ressourcen in einen einzelnen Ursprung

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

Ein Proxy

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

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 Drittanbieter (z. B. CORS Anywhere) geschrieben und gehostet werden. Beachten Sie die Auswirkungen auf den Datenschutz: Der Drittanbieter kann überwachen, wer was auf seinen Servern vertritt.

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

Das wäre in Ordnung, da das nur zwischen Mallory und Bob liegt. Bob kann sich nicht vorstellen, dass Mallory Alice ist, und Mallory Daten zur Verfügung stellen, die zwischen Alice und Bob vertraulich behandelt werden sollten.

Folglich kann Mallory diese Technik nur zum Lesen von public Daten verwenden.

Schreiben Sie etwas anderes als eine Web-App

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

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

Browsererweiterungen

Es ist möglich, dass eine Browsererweiterung die CORS-Header in die Antwort einfügt, bevor die Same Origin-Richtlinie angewendet wird.

Diese können für die Entwicklung nützlich sein, sind jedoch für eine Produktionssite nicht praktisch (die Aufforderung jedes Benutzers Ihrer Site, eine Browsererweiterung zu installieren, die ein Sicherheitsmerkmal seines Browsers deaktiviert, ist unvernünftig).

Sie können auch nur mit einfachen Anforderungen verwendet werden (Fehler bei der Verarbeitung von Preflight-OPTIONEN-Anforderungen).

Eine ordnungsgemäße Entwicklungsumgebung mit einem lokalen Entwicklungsserver server ist normalerweise ein besserer Ansatz.


Sonstige Sicherheitsrisiken

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


Zusammenfassung

  • Es gibt nichts, was Sie in Ihrem clientseitigem Code tun können, um den CORS-Zugriff auf einen anderen fremden Server zu ermöglichen.
  • Wenn Sie den Server steuern, erfolgt die Anforderung an: Fügen Sie ihm CORS-Berechtigungen hinzu.
  • Wenn Sie mit der Person, die es kontrolliert, befreundet sind: Lassen Sie sie CORS-Berechtigungen hinzufügen.
  • Wenn es sich um einen öffentlichen Dienst handelt:
    • Lesen Sie die API-Dokumentation, um zu erfahren, was sie über den Zugriff mit clientseitigem JavaScript sagen:
      • Möglicherweise werden Sie aufgefordert, bestimmte URLs zu verwenden
      • Sie könnten JSONP unterstützen
      • Sie unterstützen möglicherweise überhaupt keinen ursprungsübergreifenden Zugriff von clientseitigem 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-Anforderung auslösen, die Sie nicht benötigen. Die API gewährt möglicherweise Berechtigungen für einfache Anforderungen, jedoch nicht für Preflight-Anforderungen.
  • Wenn keine der oben genannten Bedingungen zutrifft: Lassen Sie den Browser stattdessen mit your sprechen, und lassen Sie Ihren Server die Daten vom anderen Server abrufen und weiterleiten. (Es gibt auch von Drittanbietern gehostete Dienste, die CORS-Header an öffentlich zugängliche Ressourcen anhängen, die Sie verwenden können.).
140
Quentin

Der Zielserver muss eine Cross-Origin-Anforderung zugelassen haben. Um es durch Express zuzulassen, handhaben Sie einfach die Anfrage nach http-Optionen:

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);
});
3
Daphoque

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

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

Sie können Einfache Anfragen verwenden.
Um eine 'Einfache Anforderung' auszuführen, muss die Anforderung mehrere Bedingungen erfüllen. Z.B. Erlaubt nur die Methoden POST, GET und HEAD sowie nur einige bestimmte Header (Sie können alle Bedingungen finden hier ).

Wenn Ihr Client-Code betroffene Header (z. B. "Akzeptieren") nicht explizit mit einem festen Wert in der Anforderung festlegt, tritt könnte auf, dass einige Clients diese Header automatisch mit einigen "Nicht-Standard" festlegen Werte, die dazu führen, dass der Server die Anforderung nicht als einfache Anforderung akzeptiert. Dies führt zu einem CORS-Fehler.

2
zwif

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

Mehr darüber erfahren Sie hier: CORS-Fehler mit Jquery

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

So erhalten Sie einen CORS-Post-Request (Cross-Origin Resource Sharing)

Diese Links können helfen

2
Vishnu

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

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

Nur dass ich auf die falsche URL verwiesen habe, sodass dieser Header nicht richtig reflektiert wurde (wobei ich davon ausgegangen bin, dass dies der Fall war). localhost (Frontend) -> Aufruf eines nicht gesicherten http (vermutlich https). Stellen Sie sicher, dass der API-Endpunkt vom Frontend auf das richtige Protokoll verweist.

0
morph85