Wie kann man Cookies über den Ursprung hinweg teilen? Genauer gesagt, wie wird der Set-Cookie
Header in Kombination mit dem Header verwendet Access-Control-Allow-Origin
?
Hier ist eine Erklärung meiner Situation:
Ich versuche, ein Cookie für eine API zu setzen, die localhost:4000
in einer Web-App ausgeführt wird, auf der gehostet wird localhost:3000
.
Es scheint, dass ich die richtigen Antwortheader im Browser erhalte, aber leider haben sie keine Auswirkung. Dies sind die Antwortheader:
HTTP / 1.1 200 OK Zugriffskontrolle-Zulassen-Ursprung: http: // localhost: 3000 Variieren: Ursprung, Akzeptieren-Codierung Set-Cookie: token = 0d522ba17e130d6d19eb9c25b7ac58387b798639f81ffe75bd449afbc3cc715d6b038e426adeac3316f0511dc7fae3f7; Maximales Alter = 86400; Domain = localhost: 4000; Pfad = /; Läuft ab = Di, 19. September 2017 21:11:36 GMT; HttpOnly Inhaltstyp: application / json; Zeichensatz = utf-8 Inhaltslänge: 180 ETag: W / "b4-VNrmF4xNeHGeLrGehNZTQNwAaUQ" Datum: Montag, 18. September 2017, 21:11:36 Uhr GMT Verbindung: am Leben bleiben
Außerdem kann ich das Cookie unter sehen, Response Cookies
wenn ich den Datenverkehr mithilfe der Registerkarte "Netzwerk" der Chrome-Entwicklertools überprüfe. Ich kann jedoch nicht sehen, dass auf der Registerkarte Anwendung unter ein Cookie gesetzt wird Storage/Cookies
. Ich sehe keine CORS-Fehler, daher gehe ich davon aus, dass mir etwas anderes fehlt.
Irgendwelche Vorschläge?
Update I:
Ich verwende das Anforderungsmodul in einer React-Redux-App, um eine Anforderung an einen /signin
Endpunkt auf dem Server zu senden. Für den Server benutze ich Express.
Express-Server:
res.cookie ('Token', 'xxx-xxx-xxx', {maxAge: 86400000, httpOnly: true, Domain: 'localhost: 3000'})
Anfrage im Browser:
request.post ({uri: '/ signin', json: {userName: 'userOne', Passwort: '123456'}}, (err, response, body) => { // Sachen tun })
Update II:
Ich setze Anforderungs- und Antwortheader jetzt wie verrückt und stelle sicher, dass sie sowohl in der Anforderung als auch in der Antwort vorhanden sind. Unten ist ein Screenshot. Beachten Sie die Header Access-Control-Allow-Credentials
, Access-Control-Allow-Headers
, Access-Control-Allow-Methods
und Access-Control-Allow-Origin
. Wenn ich mir das Problem ansehe , das ich bei Axios 'Github gefunden habe , habe ich den Eindruck, dass jetzt alle erforderlichen Header gesetzt sind. Trotzdem gibt es kein Glück ...
quelle
request
Modul nicht für die Verwendung im Browser vorgesehen ist. Axios scheint bisher einen tollen Job zu machen. Ich erhalte jetzt sowohl den Header:Access-Control-Allow-Credentials:true
als auchAccess-Control-Allow-Origin:http://localhost:3000
(zur Aktivierung von CORS). Dies scheint richtig, aber derSet-Cookie
Header macht nichts ...{ withCredentials: true }
tatsächlich von Axios Seite verlangt wird, müssen Server-Header ebenfalls sorgfältig überprüft werden (siehe stackoverflow.com/a/48231372/488666 )Antworten:
Was musst du machen
Gehen Sie wie folgt vor, um das erfolgreiche Empfangen und Senden von Cookies durch eine CORS-Anfrage zu ermöglichen.
Back-End (Server): Setzen Sie den HTTP-Header-
Access-Control-Allow-Credentials
Wert auftrue
. Stellen Sie außerdem sicher , dass die HTTP - HeaderAccess-Control-Allow-Origin
undAccess-Control-Allow-Headers
eingestellt sind und nicht mit einem Platzhalter*
.Weitere Informationen zum Einstellen von CORS in Express Js finden Sie in den Dokumenten hier
Front-End (Client): Setzen Sie das
XMLHttpRequest.withCredentials
Flag auftrue
. Dies kann je nach verwendeter Request-Response-Bibliothek auf unterschiedliche Weise erreicht werden:jQuery 1.5.1
xhrFields: {withCredentials: true}
ES6 fetch ()
credentials: 'include'
Axios :
withCredentials: true
Oder
Vermeiden Sie die Verwendung von CORS in Kombination mit Cookies. Sie können dies mit einem Proxy erreichen.
Wenn Sie aus irgendeinem Grund nicht vermeiden. Die Lösung ist oben.
Es stellte sich heraus, dass Chrome das Cookie nicht setzt, wenn die Domain einen Port enthält. Das Einstellen für
localhost
(ohne Port) ist kein Problem. Vielen Dank an Erwin für diesen Tipp!quelle
localhost
Überprüfung hier: stackoverflow.com/a/1188145 und auch dies kann Ihrem Fall helfen ( stackoverflow.com/questions/50966861/… )Access-Control-Allow-Origin
auf eine explizite Domäne nicht nur"*"
erforderlich ist. Dann wäre es die perfekte AntwortHinweis für Chrome Browser im Jahr 2020 veröffentlicht.
Wenn Ihr Backend-Server SameSite = None nicht festlegt, verwendet Chrome standardmäßig SameSite = Lax und verwendet dieses Cookie nicht mit {withCredentials: true} -Anforderungen.
Weitere Informationen unter https://www.chromium.org/updates/same-site .
Firefox- und Edge-Entwickler möchten diese Funktion auch in Zukunft veröffentlichen.
Spezifikation hier zu finden: https://tools.ietf.org/html/draft-west-cookie-incrementalism-01#page-8
quelle
Damit der Client Cookies aus Cross-Origin-Anfragen lesen kann, müssen Sie über Folgendes verfügen:
Alle Antworten vom Server müssen Folgendes in ihrem Header haben:
Access-Control-Allow-Credentials: true
Der Client muss alle Anfragen mit
withCredentials: true
Option sendenBei meiner Implementierung mit Angular 7 und Spring Boot habe ich Folgendes erreicht:
Serverseitig:
Der
origins = "http://my-cross-origin-url.com"
Teil wird dem AntwortheaderAccess-Control-Allow-Origin: http://my-cross-origin-url.com
jedes Servers hinzugefügtDer
allowCredentials = "true"
Teil wird zum AntwortheaderAccess-Control-Allow-Credentials: true
jedes Servers hinzugefügt. Dies ist erforderlich, damit der Client die Cookies lesen kannClient-Seite:
Mit dieser Klasse fügen Sie Ihrer gesamten Anfrage zusätzliches Material hinzu.
Der erste Teil
req = req.clone({ withCredentials: true });
ist das, was Sie benötigen, um jede Anfrage mitwithCredentials: true
Option zu senden . Dies bedeutet praktisch, dass zuerst eine OPTION-Anforderung gesendet wird, sodass Sie Ihre Cookies und das Autorisierungstoken unter ihnen erhalten, bevor Sie die tatsächlichen POST / PUT / DELETE-Anforderungen senden, an die dieses Token angehängt werden muss (im Header) Befehl an den Server, die Anforderung zu überprüfen und auszuführen.Der zweite Teil behandelt speziell ein Anti-CSRF-Token für alle Anforderungen. Liest es bei Bedarf aus dem Cookie und schreibt es in den Header jeder Anfrage.
Das gewünschte Ergebnis ist ungefähr so:
quelle
allowCredentials = "true"
in der@CrossOrigin
Anmerkung hat mir geholfen.Pims Antwort ist sehr hilfreich. In meinem Fall muss ich verwenden
Wenn es sich um eine dateTime handelt, wird der Cookie auch dann nicht an das Backend gesendet, wenn er nicht abgelaufen ist:
Ich hoffe, es ist hilfreich für zukünftige Menschen, die möglicherweise das gleiche Problem haben.
quelle
Aktualisieren Sie für Express Ihre Express-Bibliothek auf
4.17.1
die neueste stabile Version. Dann;In CorsOption: Stellen Sie
origin
zu Ihrer lokalen Host - URL oder Frontend Produktion URL undcredentials
zumtrue
BeispielIch setze meinen Ursprung dynamisch mit dem Modul config npm .
Dann in res.cookie:
Für localhost: Sie überhaupt nicht einstellen sameSite und sichere Option benötigen, können Sie festlegen können ,
httpOnly
umtrue
für HTTP - Cookie zu Verhindern , dass XSS - Angriff und andere nützliche Optionen je nach Anwendungsfall.Für Produktionsumgebung, müssen Sie festlegen ,
sameSite
umnone
für Cross-Origin - Anfrage undsecure
nachtrue
. Denken Sie daran,sameSite
funktioniert nur mit der neuesten Express-Version, da die neueste Chrome-Version nur Cookies setzthttps
, sodass eine sichere Option erforderlich ist.So habe ich meine dynamisch gemacht
quelle