Faire en sorte qu'Axios envoie automatiquement des cookies dans ses requêtes


121

J'envoie des demandes du client à mon serveur Express.js en utilisant Axios.

J'ai mis un cookie sur le client et je souhaite lire ce cookie à partir de toutes les demandes Axios sans les ajouter manuellement pour demander à la main.

Voici mon exemple de demande côté client:

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

J'ai essayé d'accéder aux en-têtes ou aux cookies en utilisant ces propriétés dans mon serveur Express.js:

req.headers
req.cookies

Aucun d'eux ne contenait de cookies. J'utilise le middleware de l'analyseur de cookies:

app.use(cookieParser())

Comment faire en sorte qu'Axios envoie automatiquement des cookies dans les demandes?

Éditer:

J'ai mis un cookie sur le client comme ceci:

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:'/'})
        }
      })
    }
...

Bien qu'il utilise également Axios, cela n'est pas pertinent pour la question. Je souhaite simplement intégrer des cookies dans toutes mes demandes une fois qu'un cookie est défini.


1
comment avez-vous placé le cookie sur le client? afficher un exemple de code s'il vous plaît :)
Tzook Bar Noy

@TzookBarNoy Ajout du code en question
Kunok

Les cookies sont définis par les serveurs avec Set-Cookie et non par le client, je suppose que vous voulez dire lire le cookie sur le client. Selon le protocole Cookie, le client doit inclure un en-tête Cookie dans ses demandes au serveur émetteur de cookie.
Hans Poo

Réponses:


241

J'ai eu le même problème et je l'ai résolu en utilisant la withCredentialspropriété.

XMLHttpRequest d'un domaine différent ne peut pas définir de valeurs de cookie pour son propre domaine à moins que withCredentials ne soit défini sur true avant d'effectuer la demande.

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

8
Si vous essayez de vous connecter à une application Express, vous devrez utiliser cors et utiliser ces paramètres. L'origine de la demande est requise. app.use (cors ({credentials: true, origin: ' localhost: 8080 '}));
DogCoffee

17
notez que cela ne fonctionnera que lorsque l' Access-Control-Allow-Originen-tête de réponse n'est pas défini sur un caractère générique (*)
Jerry Zhang

1
@JerryZhang Que voulez-vous dire? Je suis confronté au même problème, si ce Access-Control-Allow-Originn'est pas défini, *cela signifie que je ne ferai pas de demande à ce serveur à cause de
CORS

5
La réponse doit définir Access-Control-Allow-Originla valeur du domaine à partir duquel vous souhaitez effectuer une requête XHR. par exemple, https://a.comest le serveur, https://b.comest le client, et https://b.comest chargé dans le navigateur de quelqu'un et utilise XMLHTTPRequestpour faire une demande https://a.com. En plus de XMLHTTPRequest(lancé dans https://a.com) à définir withCredential: true, le serveur - https://b.comdoit également être configuré pour que l'en-tête de réponse contienneAccess-Control-Allow-Origin: https://a.com
Jerry Zhang

J'ai un petit problème avec cela ... si j'ai un serveur en tant que client (c'est-à-dire la page de réaction), que si je mets cela à true, il enverra les informations d'identification a, pas les informations d'identification b ... LOL. .. OK, ce n'est pas drôle.
golddragon007

24

TL; DR:

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


De la documentation axios

withCredentials: false, // default

withCredentials indique si les demandes de contrôle d'accès intersites doivent être effectuées à l'aide d'informations d'identification

Si vous passez { withCredentials: true }avec votre demande, cela devrait fonctionner.

Une meilleure façon serait de définir withCredentialscomme truedansaxios.defaults

axios.defaults.withCredentials = true


5
L'envoi d'informations d'identification avec chaque demande est une mauvaise pratique. Ces contrôles sont en place pour une raison. Parler à un autre service, envoyer tous vos cookies - qu'ils ne soient pas utilisés, est mûr pour l'exploitation.
colm.anseo

2
@colminator seuls les cookies qui ont le domaine du serveur comme domaine seront envoyés. (Par défaut, ils ne seront envoyés à aucun sous-domaine non plus et il peut y avoir un filtrage supplémentaire basé sur le chemin.) En effet, nous n'envoyons que les cookies du serveur qui ont été définis par le serveur.
M3RS le

15

Je ne suis pas familier avec Axios, mais pour autant que je sache en javascript et ajax, il existe une option

withCredentials: true

Cela enverra automatiquement le cookie côté client. A titre d'exemple, ce scénario est également généré avec passportjs, qui définit un cookie sur le serveur


11

Il est également important de définir les en-têtes nécessaires dans la réponse express. Ce sont ceux qui ont fonctionné pour moi:

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

L' ajout X-PINGOTHERen Access-Control-Allow-Headersest obligatoire pour moi (Node.js 6.9 avec 4,16 express, Chrome 63). Consultez la publication de JakeElder sur ce numéro de GitHub: github.com/axios/axios/issues/191#issuecomment-311069164
Frosty Z


5

pour les gens encore incapables de le résoudre, cette réponse m'a aidé. réponse stackoverflow: 34558264

TLDR; il faut définir {withCredentials: true}à la fois la requête GET et la requête POST (obtenir le cookie) pour les deux axios ainsi que pour fetch.


1
C'est crucial. J'avais oublié cela dans mon code et j'ai passé beaucoup de temps à me demander pourquoi la { withCredentials: true }requête GET n'avait aucun effet.
yogmk

1
Extrêmement important! Il y a beaucoup de discussions sur l'ajout withCredentials: trueà la configuration de la demande mais pas sur ce détail. J'ai passé près de 2 jours à essayer de résoudre le problème jusqu'à ce que je tombe sur ça
rantao

4

Comment faire en sorte qu'Axios envoie automatiquement des cookies dans les demandes?

ensemble axios.defaults.withCredentials = true;

ou pour une demande spécifique, vous pouvez utiliser axios.get(url,{withCredentials:true})

cela donnera une erreur CORS si votre 'Access-Control-Allow-Origin' est défini sur wildcard (*). Assurez-vous donc de bien préciser l'url d'origine de votre demande

par exemple: si votre front-end qui fait la demande s'exécute sur localhost: 3000, définissez l'en-tête de réponse comme

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

également mis

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

3

Vous pouvez utiliser la withCredentialspropriété pour transmettre des cookies dans la demande.

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

En définissant, { withCredentials: true }vous pouvez rencontrer un problème d'origine croisée. Pour résoudre ce problème, vous devez utiliser

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

Ici vous pouvez en savoir plus sur withCredentials


2

Vous obtenez les deux pensées mélangées.

Vous avez "react-cookie" et "axios"

react-cookie => sert à gérer le cookie côté client

axios => sert à envoyer des requêtes ajax au serveur

Avec ces informations, si vous souhaitez que les cookies du côté client soient également communiqués du côté backend, vous devrez les connecter ensemble.

Remarque du fichier Lisez-moi de "react-cookie":

Biscuits isomorphes!

Pour pouvoir accéder aux cookies utilisateur tout en effectuant le rendu du serveur, vous pouvez utiliser plugToRequest ou setRawCookie.

lien vers readme

Si c'est ce dont vous avez besoin, tant mieux.

Sinon, veuillez commenter afin que je puisse élaborer davantage.


Que fait plugToRequestexactement? J'ai pensé pour accéder aux cookies sur le serveur de nœuds, tout ce dont on a besoin est le cookie-parsermiddleware (en supposant Express)?
geoboy du

2

J'ai donc eu exactement le même problème et j'ai perdu environ 6 heures de ma vie à chercher, j'avais le

withCredentials: true

Mais le navigateur n'a toujours pas enregistré le cookie jusqu'à ce que, pour une raison étrange, j'ai eu l'idée de mélanger le paramètre de configuration:

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

Il semble que vous devriez toujours envoyer la clé «withCredentials» en premier.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.