So beheben Sie CORS-Probleme

Wahrscheinlich haben Sie bereits Fehler wie den folgenden in der JavaScript-Konsole Ihres Browsers gesehen, als Sie versuchten, AJAX-Anforderungen auszuführen:

Auf den ersten Blick ist es schwierig zu verstehen, was passiert, und herauszufinden, wo das Problem herkommt. Wir können sicher sein, dass die Fehler mit dem CORS-Mechanismus (Cross-Origin Resource Sharing) zusammenhängen. In diesem Artikel wird beschrieben, wie Sie verstehen, was gerade passiert, und wie Sie solche Probleme beheben.

CORS verstehen

Mit CORS entscheidet die Remote-Webanwendung, ob die Anforderung bearbeitet werden kann. Die CORS-Spezifikation unterscheidet zwei verschiedene Anwendungsfälle:

Diese beiden Szenarien wurden von den Entwicklern von CORS erstellt, um alte Webserver zu berücksichtigen, die die Spezifikation nicht unterstützen. Weitere Informationen finden Sie in dieser großartigen Antwort auf der StackOverflow-Website

Beachten Sie, dass einfache Anforderungen automatisch zu Preflight-Anforderungen werden, wenn Sie der Anforderung mithilfe des Authentifizierungsheaders Authentifizierung hinzufügen.

Client und Server tauschen eine Reihe von Headern aus, um das Verhalten in Bezug auf domänenübergreifende Anforderungen festzulegen. Schauen wir sie uns jetzt an. Wir werden dann beschreiben, wie sie in beiden Anwendungsfällen verwendet werden. Beginnen wir mit Überschriften für Anfragen:

Fahren wir mit den Überschriften für die Antworten fort:

Wir haben die wichtigsten CORS-Header aufgelistet. Weitere Informationen zum CORS-Prinzip finden Sie im Mozilla Developer Network .

Nachdem wir die Grundlagen beschrieben haben, wollen wir diese Prinzipien in Browsern in Aktion sehen.

Debuggen von CORS im Browser

Um herauszufinden, was passiert, müssen wir die Tools des Browsers nutzen, um die Fehlermeldung und die ausgetauschten Anfragen und Antworten anzuzeigen. Ohne diese Hinweise ist es schwierig oder sogar unmöglich, den Fehler zu verstehen.

Meistens arbeiten Entwickler mit einem REST-Client wie dem Restlet-Client  , um die Interaktionen mit dem Web-API / REST-Service zu testen. Auf dieser Ebene funktionieren Anforderungen im Browser einwandfrei, da Chrome-Erweiterungen bestimmte Berechtigungen in ihrer Konfigurationsdatei (manifest.json) angeben können. Mit dem webRequest können Sie jede Anfrage im Browser über eine Erweiterung ausführen. Hier ist ein Konfigurationsbeispiel:

{
  "manifest_version": 2,
  "short_name": "My Chrome extension",
  (...)
  "permissions": [
    (...)
    "webRequest",
    "webRequestBlocking",
    "cookies",
    "<all_urls>",
    (...)
  ],
  (...)
}

Die herkömmlichen clientseitigen Anwendungen können dies nicht und müssen bei der Ausführung domänenübergreifender Anforderungen die CORS-Regeln einhalten. Beachten Sie, dass solche Mechanismen intern vom Browser verarbeitet werden. Auf der Ebene der Anwendung, die im Browser ausgeführt wird, ist nichts zu tun.

Damit alles funktioniert, muss der CORS-Mechanismus richtig implementiert werden, dh Anforderungen und Antworten mit den richtigen Überschriften. Wir werden nun alle diese Börsen detailliert beschreiben.

Einfache Anfragen

Wie zuvor beschrieben, basieren einfache Anforderungen auf einzelnen Anforderungen, dh keinen zusätzlichen OPTIONEN-Anforderungen. Dieser Fall betrifft HTTP-GET-, HEAD-Methoden, in einigen Fällen aber auch die POST-Methode.

Wenn der Browser erkennt, dass sich die AJAX-Anforderung nicht in derselben Domäne wie die aktuelle Seite befindet, sendet er automatisch einen Origin-Header an den Server. Dies soll die CORS-Unterstützung auf dem Server für die Anforderung aktivieren, und der Browser erwartet, dass CORS-Header in der Antwort empfangen werden. Hier ist ein Beispiel:

Hinweis: Zwei Anforderungen mit demselben Host, aber nicht demselben Port, gelten nicht als in derselben Domäne.

Wir werden das gleiche Verhalten mit einer POST-Anfrage haben, die eine Formular-Payload ( Inhaltstyp) sendet : application/x-www-form-urlencoded

Stellen Sie sich vor, der Server gibt die CORS-Header (z. B. den Access-Control-Allow-Origineinen) nicht zurück, und der Browser zeigt die folgenden Fehler in der JavaScript-Konsole an:

Werfen Sie einen Blick auf die Registerkarte Netzwerk, um das Problem zu beheben. Wir können den Access-Control-Allow-OriginHeader nicht im Bereich "Antwort-Header" finden.

Das Problem liegt nicht in der Client-Anwendung, sondern in der Server-Anwendung. Um dies zu beheben, müssen wir die CORS-Unterstützung auf Serverebene aktivieren.

Einfache Anfragen sind der einfachste Fall für domänenübergreifende Anfragen. Schauen wir uns nun die vorgeprüften an.

Preflight-Anforderungen

Preflight-Anforderungen beinhalten eine zusätzliche OPTIONS-Anforderung, die vom Browser unter der Haube vor der Zielanforderung ausgeführt wird. Wir können sehr einfach in den Preflight-Modus wechseln. Beispielsweise:

Aus diesem Grund kann der Unterschied zwischen einfachen und vorgeprüften Anforderungen oft unklar sein. Dies könnte hauptsächlich auf die Unterstützung der POST-Methode zurückzuführen sein. Beispielsweise kann Ihre Anwendung für die Übermittlung einer Formularnutzlast ( Inhaltstyp) verwendet werden, jedoch nicht für eine JSON-Datei, wenn der Server die OPTIONS-Methoden nicht ordnungsgemäß verarbeitet.application/x-www-form-urlencoded

Hier ist ein Beispiel einer Preflight-Anforderung mit der Übermittlung einer JSON-Nutzlast unter Verwendung der POST-Methode:

Fix-cors-problems_5

Hier sind die Details der OPTIONEN-Anfrage:

fix-cors-problems_6

Es ist wichtig zu beachten, dass wir im Fall einer GET-Methode auch Preflight-Anforderungen haben können. Dies ist der Fall, wenn wir Authorizationder im vorherigen Abschnitt beschriebenen GET-Anforderung einen Header hinzufügen .

fix-cors-problems_7

In diesem Zusammenhang können mehrere mögliche Fehler auftreten. Werfen wir einen Blick auf die gängigsten und wie man sie behebt.

CORS-Anforderungen / -Optionen sind nicht aktiviert

Der erste Fehler besteht darin, dass OPTIONS-Methoden vom Server nicht unterstützt werden, da sie CORS überhaupt nicht unterstützen oder die Unterstützung minimal ist und Preflight-Anforderungen nicht unterstützt. In diesem Fall wird in der JavaScript-Konsole der folgende Fehler angezeigt:

fix-cors-problems_8

Wir können feststellen, dass die Nachricht das Fehlen des CORS Access-Control-Allow-Originin der Antwort und den HTTP-Statuscode 405 erwähnt. Dieser Statuscode ist ein nützlicher Hinweis, um zu verstehen, dass der Server keine OPTIONS-Anforderungen unterstützt. Werfen wir einen Blick auf die Registerkarte Netzwerk:

fix-cors-problems_9

Wir können feststellen, dass bei einem 4xx-Statuscode dasselbe Problem auftritt. Die Möglichkeit, dieses Problem zu beheben, besteht aus:

Anforderungsheader werden nicht unterstützt

Ein weiterer Fehler könnte sein, dass Header, die wir in unserer Anfrage verwenden möchten (z. B. Content-Typeoder Authorization), in der vorgeprüften CORS-Antwort unter Verwendung des Access-Control-Allow-HeadersHeaders nicht aktiviert sind . In diesem Fall wird der folgende Fehler angezeigt:

fix-cors-problems_10

In der entsprechenden Preflight-Anforderung sehen wir, dass Access-Control-Allow-Headersin der Antwort kein Header zurückgegeben wird, während die Zielanforderung den Content-TypeHeader verwenden möchte :

fix-cors-problems_11

Um dieses Problem zu beheben, fügen Sie einfach den entsprechenden Header auf der Serverseite hinzu, wenn Sie die OPTIONS-Methode verwenden. Wir werden dann folgende Anfragen haben:

fix-cors-problems_12 fix-cors-problems_13

Nicht authentifizierte OPTIONS-Anforderung

Ein weiteres häufiges Problem ist mit der Verwendung des AuthorizationHeaders verbunden. Das Ungewöhnliche ist, dass dieser Header nicht innerhalb der Preflight-Anforderung gesendet wird. Wenn die Serveranwendung versucht, alle Anforderungen, auch die vorgeprüften, zu authentifizieren, wird ein "nicht autorisierter" Fehler mit dem 401-Statuscode angezeigt:

fix-cors-problems_14

Der Server muss repariert werden, damit er Preflight-Anforderungen nicht authentifiziert. Danach würden wir die folgenden Anfragen sehen:

fix-cors-problems_15

fix-cors-problems_16

Probleme beheben

In diesem Abschnitt werden die möglichen Lösungen für die Behebung von CORS-Problemen je nach Kontext beschrieben.

Aktualisieren des Servers

Meistens besteht die einfachste Möglichkeit, das Problem zu beheben, darin, den Server zu aktualisieren. Die meisten serverseitigen Technologien bieten Unterstützung für die schnelle Konfiguration von CORS. Bei Node und ExpressJS besteht dies beispielsweise nur darin, die CORS-Middleware zu installieren und sie beim Initialisieren der Express-Anwendung zu verwenden:

var express = require('express')
  , cors = require('cors')
  , app = express();

app.use(cors());

(...)

In einigen Fällen handelt es sich bei dem Zieldienst um einen Drittanbieter, und die Aktualisierung zur Unterstützung von CORS kann nicht durchgeführt werden. Es müssen nun mehrere Ansätze in Betracht gezogen werden.

JSONP

Der erste ist JSONP. Diese Technik wird seit langem für Onlinedienste und domänenübergreifende Anforderungen verwendet, muss jedoch von den Remotediensten verwendet werden. Es besteht aus dem dynamischen Hinzufügen eines Skriptelements zur HTML-Seite, um die Anforderung auszuführen. Wenn die Antwort empfangen wird, wird der entsprechende Code analysiert und als JavaScript ausgeführt.

Aus diesem Grund muss der Antwortinhalt das folgende Format haben:

callbackName([ { name: ‘some value' }, { name: ‘some other value' }])

Der Name des Rückrufs wird als Parameter der Anforderung angegeben. In den meisten Fällen lautet der Name des Rückrufparameters gemäß Konvention callbackoder c. Hier ist eine Beispielanfrage:

http://somehost/resource/
someid?callback=callbackName

Wir können feststellen, dass ein solcher Ansatz Nachteile und Einschränkungen aufweist, da nur GET-Methoden unterstützt werden und Payload nur als Abfrageparameter bereitgestellt werden kann.

Service-Proxy

Die letzte verbleibende Möglichkeit besteht darin, einen Proxy auf der Serverseite in Ihrer Anwendung hinzuzufügen, dies erfordert jedoch ein wenig Arbeit. Wir können jedoch feststellen, dass Ionic Proxy über seine Konfigurationsdatei ionic.config.json unterstützt:

(...)
 "proxies": [{
    "path": "/yelp/v3/businesses",
    "proxyUrl": "https://api.yelp.com/v3/businesses"
 }]
(...)

CORS- und Web-APIs

Da Web-APIs auf die Kommunikation zwischen Anwendungen abzielen, unterstützen sie CORS die meiste Zeit sofort. Dies ist der Fall bei Restlet Cloud,  unserer Plattform zum Implementieren und Hosten von Web-APIs.

Beispiel: Bei einer Anforderung zum Abrufen aller Kontakte eines Geschäfts mithilfe einer Web-API (die mit dem Schnellstart-Assistenten erstellt wurde) wird die entsprechende Preflight-Anforderung von Cloud automatisch verarbeitet, wie nachfolgend beschrieben:

fix-cors-problems_17

fix-cors-problems_18

Eine interessante Funktion ist die Unterstützung von CORS für Dateien, da die meisten statischen Webserver diese Spezifikation beim Bereitstellen von Dateien nicht unterstützen. Mit Restlet Cloud können wir einen Dateispeicher in einer Web-API verfügbar machen und haben in diesem Kontext Zugriff auf die CORS-Unterstützung.

Fazit

Wie im gesamten Artikel beschrieben, zielt CORS auf domänenübergreifende Anforderungen ab und verfügt über spezifische Mechanismen, deren Debugging schwierig sein kann. Dies ist hauptsächlich auf Preflight-Anforderungen zurückzuführen, die in einigen Fällen verwendet werden und eine zusätzliche OPTIONS-Anforderung beinhalten.


Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0