Wie aktiviert man CORS mit HTTPOnly-Cookie, um Token zu sichern?

Veröffentlicht: 2021-12-29

In diesem Artikel erfahren Sie, wie Sie CORS (Cross-Origin Resource Sharing) mit HTTPOnly-Cookies aktivieren, um unsere Zugriffstoken zu sichern.

Heutzutage werden Backend-Server und Frontend-Clients auf verschiedenen Domänen bereitgestellt. Daher muss der Server CORS aktivieren, damit Clients über Browser mit dem Server kommunizieren können.

Außerdem implementieren Server eine zustandslose Authentifizierung für eine bessere Skalierbarkeit. Token werden auf der Client-Seite gespeichert und verwaltet, aber nicht auf der Server-Seite wie bei einer Sitzung. Aus Sicherheitsgründen ist es besser, Token in HTTPOnly-Cookies zu speichern.

Warum werden Cross-Origin-Anfragen blockiert?

Nehmen wir an, unsere Front-End-Anwendung wird unter https://app.geekflare.com bereitgestellt. Ein in https://app.geekflare.com geladenes Skript kann nur Ressourcen gleichen Ursprungs anfordern.

Immer wenn wir versuchen, eine ursprungsübergreifende Anfrage an eine andere Domäne https://api.geekflare.com oder einen anderen Port https://app.geekflare.com:3000 oder ein anderes Schema http://app.geekflare.com zu senden, Cross-Origin-Anfrage wird vom Browser blockiert.

Aber warum wird dieselbe Anfrage, die vom Browser blockiert wird, von jedem Backend-Server mit curl-Anfrage gesendet oder mit Tools wie dem Postboten ohne CORS-Problem gesendet. Es dient eigentlich der Sicherheit, um Benutzer vor Angriffen wie CSRF (Cross-Site Request Forgery) zu schützen.

Nehmen wir ein Beispiel: Angenommen, ein Benutzer hat sich in seinem Browser mit seinem eigenen PayPal-Konto angemeldet. Wenn wir eine Cross-Origin - Anfrage senden können paypal.com aus einem Skript auf einer anderen Domäne geladen malicious.com ohne CORS Fehler / Sperrung wie wir die gleichen Ursprung Anfrage senden.

Angreifer können ihre bösartige Seite ganz einfach https://malicious.com/transfer-money-to-attacker-account-from-user-paypal-account senden, indem sie sie in eine Kurz-URL umwandeln, um die tatsächliche URL zu verbergen. Wenn der Benutzer auf einen bösartigen Link klickt, sendet das in der Domäne malicious.com geladene Skript eine ursprungsübergreifende Anfrage an PayPal, um den Benutzerbetrag auf das PayPal-Konto des Angreifers zu überweisen. Alle Benutzer, die sich bei ihrem PayPal-Konto angemeldet und auf diesen schädlichen Link geklickt haben, verlieren ihr Geld. Jeder kann leicht Geld stehlen, ohne dass ein Benutzerwissen über ein PayPal-Konto vorhanden ist.

Aus dem oben genannten Grund blockieren Browser alle ursprungsübergreifenden Anfragen.

Was ist CORS (Cross-Origin Resource Sharing)?

CORS ist ein Header-basierter Sicherheitsmechanismus, der vom Server verwendet wird, um den Browser anzuweisen, eine ursprungsübergreifende Anfrage von vertrauenswürdigen Domänen zu senden.
Der mit CORS-Headern aktivierte Server wird verwendet, um zu verhindern, dass ursprungsübergreifende Anfragen von Browsern blockiert werden.

Wie funktioniert CORS?

Da der Server seine vertrauenswürdige Domäne bereits in seiner CORS-Konfiguration definiert hat. Wenn wir eine Anfrage an den Server senden, teilt die Antwort dem Browser mit, dass die angeforderte Domain im Header vertrauenswürdig ist oder nicht.

Es gibt zwei Arten von CORS-Anfragen:

  • Einfache Anfrage
  • Preflight-Anfrage

Einfache Anfrage:

Der einfache CORS-Anforderungsablauf teilt mit, dass er eine ursprungsübergreifende Anforderung sendet, aber eine Antwort erhalten hat. Es prüft auf Header.

  • Der Browser sendet die Anfrage an eine ursprungsübergreifende Domain mit Ursprung (https://app.geekflare.com).
  • Der Server sendet die entsprechende Antwort mit erlaubten Methoden und erlaubter Herkunft zurück.
  • Nach Erhalt der Anfrage überprüft der Browser, ob der gesendete Ursprungsheaderwert ( https://app.geekflare.com ) und der empfangene Access-Control-allow-origin-Wert ( https://app.geekflare.com ) gleich sind oder Platzhalter (*). Andernfalls wird ein CORS-Fehler ausgegeben.

Preflight-Anfrage:

CORS-Preflight Request Image which show the flow of cross-origin request with OPTIONS preflight request before sending actual request for verifying headers.

  • Abhängig vom benutzerdefinierten Anfrageparameter der Cross-Origin-Anfrage wie Methoden (PUT, DELETE) oder benutzerdefinierten Headern oder unterschiedlichen Inhaltstypen usw. Der Browser entscheidet, eine Preflight-OPTIONS-Anfrage zu senden, um zu überprüfen, ob die eigentliche Anfrage sicher ist oder nicht.
  • Nach Erhalt der Antwort (Statuscode: 204, dh kein Inhalt) überprüft der Browser die Zugriffssteuerungs- Zulassungsparameter für die eigentliche Anfrage. Wenn die Anforderungsparameter vom Server zugelassen werden. Die eigentliche gesendete und empfangene Cross-Origin-Anfrage

Wenn access-control-allow-origin: * , dann ist die Antwort für alle Ursprünge erlaubt. Aber es ist nicht sicher, wenn Sie es nicht brauchen.

Wie aktiviere ich CORS?

Um CORS für eine beliebige Domäne zu aktivieren, aktivieren Sie CORS-Header, um Ursprung, Methoden, benutzerdefinierte Header, Anmeldeinformationen usw. zuzulassen.

Der Browser liest den CORS-Header vom Server und lässt tatsächliche Anfragen vom Client erst nach Überprüfung der Anfrageparameter zu.

  • Access-Control-Allow-Origin: Um genaue Domänen anzugeben (https://app.geekflate.com, https://lab.geekflare.com) oder Wildcard(*)
  • Access-Control-Allow-Methods: Um die HTTP-Methoden (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) zuzulassen, die nur wir benötigen.
  • Access-Control-Allow-Headers: Um nur bestimmte Header zuzulassen (Autorisierung, csrf-token)
  • Access-Control-Allow-Credentials: Boolescher Wert, der verwendet wird, um ursprungsübergreifende Anmeldeinformationen (Cookies, Autorisierungsheader) zuzulassen.
  • Access-Control-Max-Age: Weist den Browser an, die Preflight-Antwort für einige Zeit zwischenzuspeichern.
  • Access-Control-Expose-Headers: Geben Sie Header an, auf die über ein clientseitiges Skript zugegriffen werden kann.

Folgen Sie diesem Tutorial, um CORS in Apache und Nginx-Webserver zu aktivieren.

Aktivieren von CORS in ExpressJS

Nehmen wir ein Beispiel für eine ExpressJS-App ohne CORS:

 const express = require('express'); const app = express() app.get('/users', function (req, res, next) { res.json({msg: 'user get'}) }); app.post('/users', function (req, res, next) { res.json({msg: 'user create'}) }); app.put('/users', function (req, res, next) { res.json({msg: 'User update'}) }); app.listen(80, function () { console.log('CORS-enabled web server listening on port 80') })

Im obigen Beispiel haben wir den API-Endpunkt des Benutzers für POST-, PUT- und GET-Methoden aktiviert, jedoch nicht für die DELETE-Methode.

Zur einfachen Aktivierung von CORS in der ExpressJS-App können Sie das cors . installieren

 npm install cors

Zugriffskontrolle-Erlauben-Ursprung

Aktivieren von CORS für alle Domänen

 app.use(cors({ origin: '*' }));

Aktivieren von CORS für eine einzelne Domäne

 app.use(cors({ origin: 'https://app.geekflare.com' }));

Wenn Sie CORS für den Ursprung https://app.geekflare.com und https://lab.geekflare.com zulassen möchten

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ] }));

Zugriffssteuerung-Zulassen-Methoden

Um CORS für alle Methoden zu aktivieren, lassen Sie diese Option im CORS-Modul in ExpressJS weg. Sondern zum Aktivieren bestimmter Methoden (GET, POST, PUT).

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'] }));

Access-Control-Allow-Header

Wird verwendet, um zuzulassen, dass andere Header als Standard-Header mit tatsächlichen Anforderungen gesendet werden.

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'] }));

Zugangskontrolle-Zulassen-Anmeldeinformationen

Auslassen dieser Option, wenn Sie nicht wollen , um den Browser zu sagen , Anmeldeinformationen auf Anfrage zu ermöglichen , auch auf withCredentials auf true gesetzt.

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true }));

Zugangskontrolle-Max.-Alter

Den Browser anweisen, die Preflight-Antwortinformationen für eine bestimmte Sekunde im Cache zwischenzuspeichern. Lassen Sie dies weg, wenn Sie die Antwort nicht zwischenspeichern möchten.

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600 }));

Die zwischengespeicherte Preflight-Antwort ist 10 Minuten lang im Browser verfügbar.

Access-Control-Expose-Header

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600, exposedHeaders: ['Content-Range', 'X-Content-Range'] }));

Wenn wir den Platzhalter (*) in exponierteHeaders einfügen, wird der Authorization-Header nicht verfügbar gemacht . Also müssen wir wie unten explizit exponieren

 app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600, exposedHeaders: ['*', 'Authorization', ] }));

Das Obige macht auch alle Header und den Autorisierungs-Header verfügbar.

Was ist ein HTTP-Cookie?

Ein Cookie ist ein kleines Datenstück, das der Server an den Client-Browser sendet. Bei späteren Anfragen sendet der Browser bei jeder Anfrage alle Cookies, die sich auf dieselbe Domain beziehen.

Cookie hat ein Attribut, das definiert werden kann, damit ein Cookie je nach Bedarf anders funktioniert.

  • Name Name des Cookies.
  • Wert: Daten des Cookies in Bezug auf den Cookie-Namen
  • Domain: Cookies werden nur an die definierte Domain gesendet
  • Pfad: Cookies, die nur nach dem definierten URL-Präfixpfad gesendet werden. Angenommen, wir haben unseren Cookie-Pfad wie path='admin/' definiert. Cookies, die nicht für die URL https://geekflare.com/expire/ gesendet werden, sondern mit dem URL-Präfix https://geekflare.com/admin/ gesendet werden
  • Max-Age/Expires(Zahl in Sekunden): Wann sollte das Cookie ablaufen. Eine Lebensdauer des Cookies macht das Cookie nach der angegebenen Zeit ungültig.
  • HTTPOnly(Boolean): Der Back-End-Server kann auf dieses HTTPOnly-Cookie zugreifen, jedoch nicht auf das clientseitige Skript, wenn es wahr ist.
  • Secure(Boolean): Cookies werden nur über eine SSL/TLS-Domain gesendet, wenn sie wahr ist.
  • sameSite(string [Strict, Lax, None]): Wird verwendet, um Cookies zu aktivieren/einzuschränken, die bei Cross-Site-Anfragen gesendet werden. Weitere Informationen zu Cookies von sameSite Sie unter MDN. Es akzeptiert drei Optionen Strikt, Lax, Keine. Der sichere Cookie-Wert ist für die Cookie-Konfiguration sameSite=None auf "true" gesetzt.

Warum HTTPOnly-Cookie für Token?

Das Speichern des vom Server gesendeten Zugriffstokens in einem clientseitigen Speicher wie lokalem Speicher , indizierter DB und Cookie (HTTPOnly nicht auf true gesetzt) ​​sind anfälliger für XSS-Angriffe. Angenommen, eine Ihrer Seiten ist für einen XSS-Angriff schwach. Angreifer können im Browser gespeicherte Benutzer-Token missbrauchen.

HTTPOnly-Cookies werden nur vom Server/Backend gesetzt/abgeholt, jedoch nicht auf der Client-Seite.

Clientseitiges Skript, das auf den Zugriff auf dieses HTTPonly-Cookie beschränkt ist. HTTPOnly-Cookies sind also nicht anfällig für XSS-Angriffe und sicherer. Weil nur der Server darauf zugreifen kann.

HTTPOnly-Cookie im CORS-aktivierten Back-End aktivieren

Das Aktivieren von Cookie in CORS erfordert die folgende Konfiguration in der Anwendung/dem Server.

  • Setzen Sie den Header Access-Control-Allow-Credentials auf true.
  • Access-Control-Allow-Origin und Access-Control-Allow-Header sollten keine Platzhalter (*) sein.
  • Das Attribut "sameSite" des Cookies sollte "Keine" sein.
  • Um den Wert von sameSite auf none zu aktivieren, setzen Sie den Wert secure auf true: Aktivieren Sie das Back-End mit SSL/TLS-Zertifikat, um im Domänennamen zu arbeiten.

Sehen wir uns einen Beispielcode an, der ein Zugriffstoken im HTTPOnly-Cookie festlegt, nachdem die Anmeldeinformationen überprüft wurden.

 const express = require('express'); const app = express(); const cors = require('cors'); app.use(cors({ origin: [ 'https://app.geekflare.com', 'https://lab.geekflare.com' ], methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['Content-Type', 'Authorization', 'x-csrf-token'], credentials: true, maxAge: 600, exposedHeaders: ['*', 'Authorization' ] })); app.post('/login', function (req, res, next) { res.cookie('access_token', access_token, { expires: new Date(Date.now() + (3600 * 1000 * 24 * 180 * 1)), //second min hour days year secure: true, // set to true if your using https or samesite is none httpOnly: true, // backend only sameSite: 'none' // set to none for cross-request }); res.json({ msg: 'Login Successfully', access_token }); }); app.listen(80, function () { console.log('CORS-enabled web server listening on port 80') });

Sie können CORS- und HTTPOnly-Cookies konfigurieren, indem Sie die obigen vier Schritte in Ihrer Backend-Sprache und Ihrem Webserver implementieren.

Sie können diesem Tutorial für Apache und Nginx folgen, um CORS zu aktivieren, indem Sie die obigen Schritte ausführen.

mitAnmeldeinformationen für Cross-Origin-Anfrage

Anmeldeinformationen (Cookie, Autorisierung) werden standardmäßig mit derselben Ursprungsanforderung gesendet. Für Cross-Origin müssen wir withCredentials auf true setzen.

XMLHttpRequest-API:

 var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://api.geekflare.com/user', true); xhr.withCredentials = true; xhr.send(null);

API abrufen:

 fetch('http://api.geekflare.com/user', { credentials: 'include' });

JQuery-Ajax:

 $.ajax({ url: 'http://api.geekflare.com/user', xhrFields: { withCredentials: true } });

Axios :

 axios.defaults.withCredentials = true

Fazit

Ich hoffe, der obige Artikel hilft Ihnen dabei, die Funktionsweise von CORS zu verstehen und CORS für ursprungsübergreifende Anforderungen im Server zu aktivieren. Warum das Speichern von Cookies in HTTPOnly sicher ist und wie mit Anmeldeinformationen, die in Clients für ursprungsübergreifende Anfragen verwendet werden.