Hacer que Axios envíe cookies en sus solicitudes automáticamente

121

Estoy enviando solicitudes del cliente a mi servidor Express.js usando Axios.

Configuré una cookie en el cliente y quiero leer esa cookie de todas las solicitudes de Axios sin agregarlas manualmente para solicitarlas manualmente.

Este es mi ejemplo de solicitud del lado del cliente:

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

Intenté acceder a los encabezados o cookies utilizando estas propiedades en mi servidor Express.js:

req.headers
req.cookies

Ninguno de ellos contenía cookies. Estoy usando el middleware del analizador de cookies:

app.use(cookieParser())

¿Cómo hago para que Axios envíe cookies en solicitudes automáticamente?

Editar:

Configuré cookies en el cliente de esta manera:

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

Si bien también utiliza Axios, no es relevante para la pregunta. Simplemente quiero incrustar cookies en todas mis solicitudes una vez que se establece una cookie.

Kunok
fuente
1
¿Cómo configuró la cookie en el cliente? muestre un ejemplo de código por favor :)
Tzook Bar Noy
@TzookBarNoy Código agregado en cuestión
Kunok
Las cookies las establecen los servidores con Set-Cookie, no el cliente, supongo que te refieres a leer la cookie en el cliente. Según el protocolo de cookies, el cliente debe incluir un encabezado de cookie en sus solicitudes al servidor emisor de cookies.
Hans Poo

Respuestas:

241

Tuve el mismo problema y lo solucioné usando la withCredentialspropiedad.

XMLHttpRequest de un dominio diferente no puede establecer valores de cookie para su propio dominio a menos que withCredentials esté establecido en true antes de realizar la solicitud.

axios.get('some api url', {withCredentials: true});
dedo
fuente
8
Si está intentando conectarse a una aplicación Express, deberá usar cors y usar esta configuración. Se requiere el origen de la solicitud. app.use (cors ({credentials: true, origin: ' localhost: 8080 '}));
DogCoffee
17
tenga en cuenta que esto solo funcionará cuando el Access-Control-Allow-Originencabezado de respuesta no esté configurado como comodín (*)
Jerry Zhang
1
@JerryZhang ¿Qué quieres decir? Estoy enfrentando el mismo problema, si Access-Control-Allow-Originno está configurado *, significa que no haré una solicitud a ese servidor debido a CORS correcto
samayo
5
La respuesta debe establecer Access-Control-Allow-Originel valor del dominio desde el que desea realizar la solicitud XHR. por ejemplo, https://a.comes el servidor, https://b.comes el cliente y https://b.comse carga en el navegador de alguien y se usa XMLHTTPRequestpara realizar una solicitud https://a.com. Además de XMLHTTPRequest(iniciado en https://a.com) para configurar withCredential: true, el servidor - https://b.comtambién debe configurarse para que el encabezado de respuesta contengaAccess-Control-Allow-Origin: https://a.com
Jerry Zhang
Tengo un pequeño problema con esto ... si tengo a como servidor b como cliente (es decir, página de reacción), que si configuro esto en verdadero, enviará las credenciales a, no las credenciales b ... LOL. .. Está bien, no es gracioso.
golddragon007
24

TL; DR:

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


De la documentación de axios

withCredentials: false, // default

withCredentials indica si las solicitudes de control de acceso entre sitios deben realizarse con credenciales

Si pasa { withCredentials: true }con su solicitud, debería funcionar.

Una mejor manera sería establecer withCredentialscomo trueenaxios.defaults

axios.defaults.withCredentials = true

Fatih Acet
fuente
5
Enviar credenciales con cada solicitud es una mala práctica. Estos controles están en su lugar por una razón. Hablar con otro servicio, enviar todas sus cookies, ya sea que se utilicen o no, está listo para su explotación.
colm.anseo
2
@colminator solo se enviarán las cookies que tengan el dominio del servidor como su dominio. (De forma predeterminada, tampoco se enviarán a ningún subdominio y puede haber más filtrado en función de la ruta). En efecto, solo enviamos las cookies del servidor que fueron establecidas por el servidor.
M3RS
15

No estoy familiarizado con Axios, pero hasta donde sé, en javascript y ajax hay una opción

withCredentials: true

Esto enviará automáticamente la cookie al lado del cliente. Como ejemplo, este escenario también se genera con passportjs, que establece una cookie en el servidor.

RITESH ARORA
fuente
11

También es importante establecer los encabezados necesarios en la respuesta rápida. Estos son los que me funcionaron:

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();
});
Eyk Rehbein
fuente
Añadiendo X-PINGOTHERen Access-Control-Allow-Headersha sido obligatoria para mí (Node.js 6,9 con 4,16 expreso, Chrome 63). Consulte la publicación de JakeElder sobre este problema de GitHub: github.com/axios/axios/issues/191#issuecomment-311069164
Frosty Z
5

para las personas que aún no pueden resolverlo, esta respuesta me ayudó. respuesta de stackoverflow: 34558264

TLDR; es necesario configurar {withCredentials: true}tanto la solicitud GET como la solicitud POST (obtener la cookie) para ambos axios y fetch.

the_dangoria
fuente
1
Esto es crucial. Había pasado por alto esto en mi código y pasé mucho tiempo preguntándome por qué la { withCredentials: true }solicitud GET no tuvo ningún efecto.
yogmk
1
¡Extremadamente importante! Hay mucha discusión sobre cómo agregar withCredentials: truea la configuración de la solicitud, pero no este detalle. Pasé casi 2 días tratando de resolver el problema hasta que me encontré con esto
R. Antao
4

¿Cómo hago para que Axios envíe cookies en solicitudes automáticamente?

conjunto axios.defaults.withCredentials = true;

o para alguna solicitud específica puedes usar axios.get(url,{withCredentials:true})

esto dará un error CORS si su 'Access-Control-Allow-Origin' está configurado como comodín (*). Por lo tanto, asegúrese de especificar la URL de origen de su solicitud.

por ejemplo: si su interfaz que realiza la solicitud se ejecuta en localhost: 3000, establezca el encabezado de respuesta como

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

también establece

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

Puede utilizar la withCredentialspropiedad para pasar cookies en la solicitud.

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

Al configurar { withCredentials: true }, puede encontrar un problema de origen cruzado. Para resolver eso necesitas usar

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

Aquí puede leer sobre con Credenciales

Sunil Garg
fuente
2

Estás mezclando las dos ideas.

Tienes "react-cookie" y "axios"

react-cookie => es para manejar la cookie en el lado del cliente

axios => es para enviar solicitudes ajax al servidor

Con esa información, si desea que las cookies del lado del cliente también se comuniquen en el lado del backend, deberá conectarlas.

Nota del archivo Léame "react-cookie":

¡Galletas isomorfas!

Para poder acceder a las cookies del usuario mientras realiza la renderización del servidor, puede utilizar plugToRequest o setRawCookie.

enlace al archivo Léame

Si esto es lo que necesitas, genial.

Si no es así, comente para que pueda dar más detalles.

Tzook Bar Noy
fuente
¿Qué hace plugToRequestexactamente? Pensé para acceder a las cookies en el servidor de nodo, ¿todo lo que se necesita es el cookie-parsermiddleware (asumiendo Express)?
geoboy
2

Así que tuve exactamente el mismo problema y perdí alrededor de 6 horas de mi vida buscando, tuve el

withCredentials: true

Pero el navegador aún no guardó la cookie hasta que, por alguna extraña razón, tuve la idea de cambiar la configuración:

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

Parece que siempre debe enviar primero la clave 'withCredentials'.

Luigi Córdoba Granera
fuente