Lassen Sie Axios automatisch Cookies in seinen Anfragen senden


121

Ich sende mit Axios Anfragen vom Client an meinen Express.js-Server.

Ich habe auf dem Client ein Cookie gesetzt und möchte dieses Cookie aus allen Axios-Anforderungen lesen, ohne sie manuell zur manuellen Anforderung hinzuzufügen.

Dies ist das Beispiel für eine clientseitige Anfrage:

axios.get(`some api url`).then(response => ...

Ich habe versucht, mithilfe dieser Eigenschaften auf meinem Express.js-Server auf Header oder Cookies zuzugreifen:

req.headers
req.cookies

Keiner von ihnen enthielt Cookies. Ich verwende die Middleware für Cookie-Parser:

app.use(cookieParser())

Wie kann ich Axios dazu bringen, Cookies in Anfragen automatisch zu senden?

Bearbeiten:

Ich setze Cookies auf dem Client wie folgt:

import cookieClient from 'react-cookie'

...
let cookie = cookieClient.load('cookie-name')
if(cookie === undefined){
      axios.get('path/to/my/cookie/api').then(response => {
        if(response.status == 200){
          cookieClient.save('cookie-name', response.data, {path:'/'})
        }
      })
    }
...

Während es auch Axios verwendet, ist es für die Frage nicht relevant. Ich möchte einfach Cookies in alle meine Anfragen einbetten, sobald ein Cookie gesetzt ist.


1
Wie haben Sie das Cookie auf dem Client gesetzt? Codebeispiel bitte
anzeigen

@ TzookBarNoy Code in Frage
hinzugefügt

Cookies werden von Servern mit Set-Cookie gesetzt, nicht vom Client. Ich denke, Sie meinen das Lesen des Cookies auf dem Client. Gemäß dem Cookie-Protokoll sollte der Client einen Cookie-Header in seine Anforderungen an den Server des Cookie-Ausstellers aufnehmen.
Hans Poo

Antworten:


240

Ich hatte das gleiche Problem und habe es mithilfe der withCredentialsEigenschaft behoben .

XMLHttpRequest aus einer anderen Domäne kann keine Cookie-Werte für die eigene Domäne festlegen, es sei denn, withCredentials wird vor der Anforderung auf true gesetzt.

axios.get('some api url', {withCredentials: true});

8
Wenn Sie versuchen, eine Verbindung zu einer Express-App herzustellen, müssen Sie cors verwenden und diese Einstellungen verwenden. Der Ursprung der Anfrage ist erforderlich. app.use (cors ({Anmeldeinformationen: true, Ursprung: ' localhost: 8080 '}));
DogCoffee

17
Beachten Sie, dass dies nur funktioniert, wenn der Access-Control-Allow-OriginHeader der Antwort nicht auf Platzhalter (*) gesetzt ist
Jerry Zhang

1
@ JerryZhang Was meinst du? Ich stehe vor dem gleichen Problem, wenn Access-Control-Allow-Origines nicht eingestellt ist, *bedeutet dies, dass ich wegen CORS-Recht keine Anfrage an diesen Server stellen werde
samayo

5
Die Antwort muss den Access-Control-Allow-OriginWert von set für die Domäne festlegen , von der aus Sie eine XHR-Anforderung stellen möchten. zB https://a.comist der Server, https://b.comist der Client und https://b.comwird in den Browser einer anderen Person geladen und verwendet XMLHTTPRequest, um eine Anfrage an zu stellen https://a.com. Zusätzlich zum Einstellen XMLHTTPRequest(initiiert in https://a.com) withCredential: truemuss der Server - https://b.comauch so konfiguriert werden, dass der Antwortheader enthältAccess-Control-Allow-Origin: https://a.com
Jerry Zhang

Ich habe ein kleines Problem damit ... Wenn ich a als Server b als Client habe (dh Seite reagieren), als wenn ich dies auf true setze, werden die Anmeldeinformationen a gesendet, nicht die Anmeldeinformationen b ... LOL. .. OK, es ist nicht lustig.
Golddragon007

24

TL; DR:

{ withCredentials: true } oder axios.defaults.withCredentials = true


Aus der Axios-Dokumentation

withCredentials: false, // default

withCredentials Gibt an, ob standortübergreifende Zugriffssteuerungsanforderungen mithilfe von Anmeldeinformationen gestellt werden sollen

Wenn Sie { withCredentials: true }mit Ihrer Anfrage bestehen, sollte es funktionieren.

Ein besserer Weg wäre das Einstellen withCredentialswie trueinaxios.defaults

axios.defaults.withCredentials = true


5
Das Senden von Anmeldeinformationen bei jeder Anfrage ist eine schlechte Praxis. Diese Kontrollen sind aus einem bestimmten Grund vorhanden. Wenn Sie mit einem anderen Dienst sprechen und alle Ihre Cookies senden - unabhängig davon, ob sie verwendet werden oder nicht -, können Sie sie ausnutzen.
colm.anseo

2
@colminator Es werden nur Cookies gesendet, deren Domäne die Serverdomäne ist. (Standardmäßig werden sie auch nicht an Subdomains gesendet, und es kann eine weitere Filterung basierend auf dem Pfad erfolgen.) Tatsächlich senden wir nur die Server-Cookies, die vom Server gesetzt wurden.
M3RS

15

Ich bin mit Axios nicht vertraut, aber soweit ich in Javascript und Ajax weiß, gibt es eine Option

withCredentials: true

Dadurch wird das Cookie automatisch an den Client gesendet. Dieses Szenario wird beispielsweise auch mit passportjs generiert, wodurch ein Cookie auf dem Server gesetzt wird


11

Es ist auch wichtig, die erforderlichen Header in der Express-Antwort festzulegen. Dies sind diejenigen, die für mich gearbeitet haben:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', yourExactHostname);
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

Das Hinzufügen X-PINGOTHERzu Access-Control-Allow-Headerswar für mich obligatorisch (Node.js 6.9 mit Express 4.16, Chrome 63). Überprüfen Sie JakeElder 's Beitrag zu diesem GitHub-Problem: github.com/axios/axios/issues/191#issuecomment-311069164
Frosty Z


5

Für Leute, die es immer noch nicht lösen können, hat mir diese Antwort geholfen. Antwort auf Stapelüberlauf: 34558264

TLDR; Man muss {withCredentials: true}sowohl die GET-Anforderung als auch die POST-Anforderung (Abrufen des Cookies) sowohl für Axios als auch für Fetch festlegen.


1
Das ist entscheidend. Ich hatte dies in meinem Code übersehen und viel Zeit damit verbracht, mich zu fragen, warum die { withCredentials: true }GET-Anfrage keine Auswirkungen hatte.
Yogmk

1
Extrem wichtig! Es gibt viele Diskussionen über das Hinzufügen withCredentials: truezur Anforderungskonfiguration, aber nicht dieses Detail. Ich habe fast 2 Tage lang versucht, das Problem zu lösen, bis ich darauf stieß
R. Antao

4

Wie kann ich Axios dazu bringen, Cookies in Anfragen automatisch zu senden?

einstellen axios.defaults.withCredentials = true;

oder für eine bestimmte Anfrage können Sie verwenden axios.get(url,{withCredentials:true})

Dies führt zu einem CORS-Fehler, wenn Ihr 'Access-Control-Allow-Origin' auf Platzhalter (*) gesetzt ist. Stellen Sie daher sicher, dass Sie die URL des Ursprungs Ihrer Anfrage angeben

Zum Beispiel: Wenn Ihr Front-End, das die Anforderung stellt, auf localhost: 3000 ausgeführt wird, setzen Sie den Antwortheader auf

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

auch eingestellt

res.setHeader('Access-Control-Allow-Credentials',true);

3

Sie können die withCredentialsEigenschaft verwenden, um Cookies in der Anfrage zu übergeben.

axios.get(`api_url`, { withCredentials: true })

Bei der Einstellung { withCredentials: true }kann es zu Problemen mit dem Ursprung kommen. Um das zu lösen, müssen Sie verwenden

expressApp.use(cors({ credentials: true, origin: "http://localhost:8080" }));

Hier können Sie über withCredentials lesen


2

Sie bekommen die beiden Gedanken gemischt.

Sie haben "React-Cookie" und "Axios"

React-Cookie => dient zur Behandlung des Cookies auf der Clientseite

axios => dient zum Senden von Ajax-Anfragen an den Server

Wenn Sie mit diesen Informationen möchten, dass die Cookies von der Client-Seite auch auf der Backend-Seite kommuniziert werden, müssen Sie sie miteinander verbinden.

Hinweis aus "React-Cookie" Readme:

Isomorphe Kekse!

Um beim Rendern von Servern auf Benutzer-Cookies zugreifen zu können, können Sie plugToRequest oder setRawCookie verwenden.

Link zur Readme

Wenn es das ist, was du brauchst, großartig.

Wenn nicht, kommentieren Sie bitte, damit ich mehr ausarbeiten kann.


Was macht plugToRequestgenau? Ich dachte, um auf Cookies auf dem Knotenserver zuzugreifen, braucht man nur die cookie-parserMiddleware (vorausgesetzt Express)?
Geoboy

2

Also hatte ich genau das gleiche Problem und verlor ungefähr 6 Stunden meines Lebens auf der Suche, ich hatte das

withCredentials: true

Aber der Browser hat den Cookie immer noch nicht gespeichert, bis ich aus irgendeinem seltsamen Grund auf die Idee kam, die Konfigurationseinstellung zu mischen:

Axios.post(GlobalVariables.API_URL + 'api/login', {
        email,
        password,
        honeyPot
    }, {
        withCredentials: true,
        headers: {'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'
    }});

Scheint, als sollten Sie immer zuerst den Schlüssel 'withCredentials' senden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.