Cross-Origin Resource Sharing (CORS)

Ursprungsübergreifende Ressourcen sicher teilen

Mariko Kosaka

Die Same-Origin-Policy des Browsers blockiert das Lesen einer Ressource von einem anderen Ursprung. Dieser Mechanismus verhindert, dass eine schädliche Website die Daten einer anderen Website liest, aber er verhindert auch eine legitime Verwendung. Wie können Sie Wetterdaten aus einem anderen Land abrufen?

In einer modernen Webanwendung möchte eine Anwendung häufig Ressourcen aus einem anderen Ursprung abrufen. Beispiel: Sie möchten JSON-Daten aus einer anderen Domain abrufen oder Bilder von einer anderen Website in ein <canvas>-Element laden.

Mit anderen Worten: Es gibt öffentliche Ressourcen, die für alle zur Ansicht verfügbar sein sollten, aber die Richtlinie für denselben Ursprung blockiert dies. Entwickler haben Behelfslösungen wie JSONP verwendet, aber Cross-Origin Resource Sharing (CORS) behebt dies standardmäßig.

Wenn Sie CORS aktivieren, teilt der Server dem Browser mit, dass er eine zusätzliche Quelle verwenden darf.

Wie funktioniert eine Ressourcenanforderung im Web?

Anfrage und Antwort
Abbildung: Illustrierte Clientanfrage und Serverantwort

Ein Browser und ein Server können mithilfe des Hypertext Transfer Protocol (HTTP) Daten über das Netzwerk austauschen. HTTP definiert die Kommunikationsregeln zwischen dem Anfragenden und dem Antwortenden, einschließlich der Informationen, die zum Abrufen einer Ressource erforderlich sind.

Der HTTP-Header wird verwendet, um die Art des Nachrichtenaustauschs zwischen dem Client und dem Server auszuhandeln, und wird zur Bestimmung des Zugriffs verwendet. Sowohl die Browseranfrage als auch die Antwortnachricht des Servers werden in zwei Teile unterteilt: header und body:

Informationen zur Nachricht wie den Nachrichtentyp oder die Codierung der Nachricht. Ein Header kann eine Vielzahl von Informationen enthalten, die als Schlüssel/Wert-Paare ausgedrückt werden. Anfrageheader und Antwortheader enthalten unterschiedliche Informationen.

Beispiel für einen Anfrageheader

Accept: text/html
Cookie: Version=1

Das Ergebnis oben entspricht der Anweisung "Ich möchte HTML als Antwort erhalten. Hier ist ein Keks, den ich habe.“

Beispiel für einen Antwortheader

Content-Encoding: gzip
Cache-Control: no-store

Das obenstehende Ergebnis entspricht der Aussage "Daten sind mit gzip codiert. Speichern Sie das bitte nicht im Cache.“

body

Die Nachricht selbst Dies kann z. B. Nur-Text, ein binäres Bild, JSON, HTML usw. sein.

Wie funktioniert CORS?

Denken Sie daran, dass die Same-Origin-Policy den Browser anweist, ursprungsübergreifende Anfragen zu blockieren. Wenn Sie eine öffentliche Ressource aus einem anderen Ursprung abrufen möchten, muss der ressourcen bereitstellende Server dem Browser mitteilen, dass dieser Ursprung, von dem die Anfrage stammt, auf meine Ressource zugreifen kann. Der Browser merkt sich dies und ermöglicht Cross-Origin Resource Sharing.

Schritt 1: Client- bzw. Browseranfrage

Wenn der Browser eine ursprungsübergreifende Anfrage sendet, fügt er einen Origin-Header mit dem aktuellen Ursprung (Schema, Host und Port) hinzu.

Schritt 2: Serverantwort

Wenn ein Server diesen Header sieht und Zugriff erlauben möchte, muss er der Antwort einen Access-Control-Allow-Origin-Header hinzufügen, in dem der anfragende Ursprung angegeben ist (oder *, um jeden Ursprung zuzulassen).

Schritt 3: Browser erhält Antwort

Wenn der Browser diese Antwort mit einem entsprechenden Access-Control-Allow-Origin-Header erkennt, lässt er zu, dass die Antwortdaten an die Clientwebsite weitergegeben werden.

CORS in Aktion sehen

Hier ist ein kleiner Webserver, der Express verwendet.

Für den ersten Endpunkt (Zeile 8) ist kein Antwortheader festgelegt. Er sendet lediglich eine Datei als Antwort.

  • Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.
  • Drücken Sie Strg + Umschalttaste + J (oder Befehlstaste + Option + J auf dem Mac), um die Entwicklertools zu öffnen.
  • Klicken Sie auf den Tab Console.
  • Versuchen Sie es mit dem folgenden Befehl:
fetch('https://cors-demo.glitch.me/', {mode:'cors'})

Sie sollten folgende Fehlermeldung sehen:

request has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
is present on the requested resource.

Der zweite Endpunkt (Zeile 13) sendet dieselbe Datei als Antwort, fügt jedoch Access-Control-Allow-Origin: * im Header hinzu. Versuchen Sie in der Konsole,

fetch('https://cors-demo.glitch.me/allow-cors', {mode:'cors'})

Diesmal sollte Ihre Anfrage nicht blockiert werden.

Anmeldedaten für CORS freigeben

Aus Datenschutzgründen wird CORS normalerweise für "anonyme Anfragen" verwendet, also für Anfragen, bei denen der Antragsteller in der Anfrage nicht identifiziert wird. Wenn Sie mit CORS Cookies senden möchten (die den Absender identifizieren könnten), müssen Sie der Anfrage und Antwort zusätzliche Header hinzufügen.

Anfragen

Fügen Sie den Abrufoptionen credentials: 'include' hinzu, wie unten dargestellt. Dies schließt das Cookie mit der Anfrage ein.

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Antwort

Access-Control-Allow-Origin muss auf einen bestimmten Ursprung festgelegt werden (kein Platzhalter mit *) und Access-Control-Allow-Credentials auf true festgelegt werden.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Preflight-Anfragen für komplexe HTTP-Aufrufe

Wenn eine Webanwendung eine komplexe HTTP-Anfrage benötigt, fügt der Browser am Anfang der Anfragekette eine Preflight-Anfrage hinzu.

Die CORS-Spezifikation definiert eine komplexe Anfrage als

  • Eine Anfrage, die andere Methoden als GET, POST oder HEAD verwendet
  • Eine Anfrage, die andere Header als Accept, Accept-Language oder Content-Language enthält
  • Eine Anfrage mit einem anderen Content-Type-Header als application/x-www-form-urlencoded, multipart/form-data oder text/plain

Browser erstellen bei Bedarf eine Preflight-Anfrage. Es handelt sich um eine OPTIONS-Anfrage (siehe unten), die vor der eigentlichen Anfragenachricht gesendet wird.

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

Auf Serverseite muss eine Anwendung auf die Preflight-Anfrage mit Informationen zu den Methoden antworten, die die Anwendung von diesem Ursprung akzeptiert.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

Die Serverantwort kann auch einen Access-Control-Max-Age-Header enthalten, um die Dauer (in Sekunden) für das Speichern von Preflight-Ergebnissen im Cache anzugeben, damit der Client nicht jedes Mal eine Preflight-Anfrage stellen muss, wenn er eine komplexe Anfrage sendet.