Wie aktiviere ich CORS mit HTTPOnly-Cookie für sicheres Token?

In diesem Artikel erfahren Sie, wie Sie CORS (Cross-Origin Resource Sharing) mit HTTPOnly-Cookie 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 zustandslose Authentifizierung für eine bessere Skalierbarkeit. Token werden auf der Clientseite gespeichert und gepflegt, aber nicht auf der Serverseite wie Sitzungen. Aus Sicherheitsgründen ist es besser, Token in HTTPOnly-Cookies zu speichern.

Inhaltsverzeichnis

Warum werden Cross-Origin-Anfragen blockiert?

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

Immer wenn wir versuchen, eine ursprungsübergreifende Anfrage an eine andere Domain https://api.wdzwdz.com oder einen anderen Port https://app.wdzwdz.com:3000 oder ein anderes Schema http://app.wdzwdz.com zu senden, wird die Ursprungsübergreifende Anfragen werden vom Browser blockiert.

Aber warum wird dieselbe vom Browser blockierte Anfrage 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 eigenen PayPal-Konto in seinem Browser angemeldet. Wenn wir eine ursprungsübergreifende Anfrage an paypal.com von einem Skript senden können, das auf einer anderen Domäne bösartig.com geladen ist, ohne dass ein CORS-Fehler/eine CORS-Blockierung vorliegt, als ob wir die Anfrage mit demselben Ursprung senden würden.

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

Aus dem oben genannten Grund blockieren Browser alle Cross-Origin-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 Server aktiviert mit CORS-Headern, die verwendet werden, um Cross-Origin-Anfragen zu vermeiden, die 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, ob die angeforderte Domain in ihrem Header vertrauenswürdig ist oder nicht.

  TCP/IP-Protokollarchitekturmodell – Wie funktioniert es?

Es gibt zwei Arten von CORS-Anfragen:

  • Einfache Anfrage
  • Preflight-Anfrage

Einfache Anfrage:

  • Der Browser sendet die Anfrage an eine Cross-Origin-Domain mit origin(https://app.wdzwdz.com).
  • Der Server sendet die entsprechende Antwort mit erlaubten Methoden und erlaubtem Ursprung zurück.
  • Nach Erhalt der Anfrage überprüft der Browser, ob der gesendete Origin-Header-Wert (https://app.wdzwdz.com) und der empfangene Access-Control-Allow-Origin-Wert (https://app.wdzwdz.com) identisch sind oder Platzhalter

. Andernfalls wird ein CORS-Fehler ausgegeben.

  • Preflight-Anfrage:
  • Abhängig von den benutzerdefinierten Anforderungsparametern aus der Cross-Origin-Anforderung wie Methoden (PUT, DELETE) oder benutzerdefinierte Header oder unterschiedliche Inhaltstypen usw. Der Browser entscheidet, eine Preflight-OPTIONS-Anforderung zu senden, um zu prüfen, ob die eigentliche Anforderung sicher gesendet werden kann oder nicht.

Nach Erhalt der Antwort (Statuscode: 204, was bedeutet, dass kein Inhalt vorhanden ist) überprüft der Browser die Zugriffssteuerungs-Erlaubnis-Parameter für die eigentliche Anfrage. Wenn die Anforderungsparameter vom Server zugelassen werden. Die tatsächlich gesendete und empfangene ursprungsübergreifende Anfrage

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

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 zu, nachdem er die Anfrageparameter überprüft hat.
  • Access-Control-Allow-Origin: Um genaue Domänen (https://app.geekflate.com, https://lab.wdzwdz.com) oder Platzhalter anzugeben
  • Access-Control-Allow-Methods: Um die HTTP-Methoden (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS) zuzulassen, die nur wir brauchen.
  • Access-Control-Allow-Headers: Um nur bestimmte Header zuzulassen (Authorization, csrf-token)
  • Access-Control-Allow-Credentials: Boolescher Wert, der verwendet wird, um Cross-Origin-Credentials (Cookies, Authorization Header) 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 clientseitige Skripts zugegriffen werden kann.

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

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')
})

Aktivieren von CORS in ExpressJS

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

npm install cors

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

Zur einfachen Aktivierung von CORS in der ExpressJS-App können Sie die Datei cors

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

Access-Control-Allow-Origin

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

Aktivieren von CORS für alle Domänen

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

Aktivieren von CORS für eine einzelne Domäne

Wenn Sie CORS für die Herkunft https://app.wdzwdz.com und https://lab.wdzwdz.com zulassen möchten

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

Access-Control-Allow-Methoden

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

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

Access-Control-Allow-Header

Wird verwendet, um zuzulassen, dass andere als die Standardheader 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'],
    credentials: true
}));

Zugriffssteuerung-Erlauben-Anmeldeinformationen

Lassen Sie dies weg, wenn Sie dem Browser nicht mitteilen möchten, Anmeldeinformationen auf Anfrage zuzulassen, selbst wenn withCredentials auf „true“ gesetzt ist.

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

Zugriffskontrolle-Max-Alter

  Samsung bläst mit McAfee alles auf – sogar Smart-TVs

Um den Browser anzuweisen, 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,
    exposedHeaders: ['Content-Range', 'X-Content-Range']
}));

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

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', ]
}));

Access-Control-Expose-Header

Wenn wir den Platzhalter setzen

in ExposedHeaders wird der Authorization-Header nicht verfügbar gemacht. Also müssen wir explizit wie unten exponieren

Das Obige zeigt auch alle Header und den Authorization-Header an.

  • Was ist ein HTTP-Cookie?
  • Ein Cookie ist ein kleines Datenelement, das der Server an den Client-Browser sendet. Bei späteren Anfragen sendet der Browser bei jeder Anfrage alle Cookies, die sich auf dieselbe Domäne beziehen.
  • Cookie hat sein Attribut, das definiert werden kann, damit ein Cookie je nach Bedarf anders funktioniert.
  • Name Name des Cookies.
  • Wert: Daten des Cookies bzw. des Cookie-Namens
  • 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 werden nicht für die URL https://wdzwdz.com/expire/ gesendet, sondern mit dem URL-Präfix https://wdzwdz.com/admin/
  • Max-Age/Expires(Zahl in Sekunden): Wann soll das Cookie ablaufen. Eine Lebensdauer des Cookies macht das Cookie nach der angegebenen Zeit ungültig. [Strict, Lax, None]HTTPOnly(Boolean): Der Back-End-Server kann auf dieses HTTPOnly-Cookie zugreifen, aber nicht auf das clientseitige Skript, wenn es wahr ist. Sicher (Boolean): Cookies werden nur dann über eine SSL/TLS-Domäne gesendet, wenn sie wahr sind.gleicheSite(Zeichenfolge

): Wird zum Aktivieren/Einschränken von Cookies verwendet, die bei Cross-Site-Anfragen gesendet werden. Weitere Informationen zu Cookies finden Sie auf derselben Website

MDN

  So reparieren Sie ein Echo oder Google Home, das keine WLAN-Verbindung herstellt

. Es akzeptiert drei Optionen: Strict, Lax, None. Cookie-Sicherheitswert für die Cookie-Konfiguration sameSite=None auf „true“ gesetzt.

Warum HTTPOnly-Cookie für Token?

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

HTTPOnly-Cookies werden nur vom Server/Backend gesetzt/abgerufen, aber nicht auf der Clientseite.

  • Clientseitiges Skript, das auf den Zugriff auf dieses Nur-HTTP-Cookie beschränkt ist. Daher sind HTTPOnly-Cookies nicht anfällig für XSS-Angriffe und sicherer. Weil es nur vom Server aus zugänglich ist.
  • Aktivieren Sie das HTTPOnly-Cookie im CORS-fähigen Back-End
  • Das Aktivieren von Cookies in CORS erfordert die folgende Konfiguration in der Anwendung/dem Server.
  • Setzen Sie den Access-Control-Allow-Credentials-Header auf „true“.

Access-Control-Allow-Origin und Access-Control-Allow-Headers sollten keine Platzhalter sein

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') 
}); 

.

Das Cookie-Attribut sameSite sollte None sein.

Um den sameSite-Wert auf none zu aktivieren, setzen Sie den sicheren Wert auf true: Enable backend with SSL/TLS certificate to work in the domain name.

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

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

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

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

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

withCredentials für Cross-Origin-Anfrage

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

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

axios.defaults.withCredentials = true

XMLHttpRequest-API

API abrufen

JQuery AjaxAxiosFazit Ich hoffe, der obige Artikel hilft Ihnen dabei, die Funktionsweise von CORS zu verstehen und CORS für ursprungsübergreifende Anforderungen auf dem Server zu aktivieren. Warum das Speichern von Cookies in HTTPOnly sicher ist und wie mitCredentials, die in Clients für Cross-Origin-Anfragen verwendet werden.