¿Cómo compartir cookies de origen cruzado? Más específicamente, ¿cómo usar el Set-Cookie
encabezado en combinación con el encabezado Access-Control-Allow-Origin
?
Aquí hay una explicación de mi situación:
Estoy intentando configurar una cookie para una API que se ejecuta localhost:4000
en una aplicación web alojada en localhost:3000
.
Parece que recibo los encabezados de respuesta correctos en el navegador, pero desafortunadamente no tienen ningún efecto. Estos son los encabezados de respuesta:
HTTP / 1.1 200 OK Acceso-Control-Permitir-Origen: http: // localhost: 3000 Variar: Origen, Aceptar codificación Set-Cookie: token = 0d522ba17e130d6d19eb9c25b7ac58387b798639f81ffe75bd449afbc3cc715d6b038e426adeac3316f0511dc7fae3f7; Edad máxima = 86400; Dominio = localhost: 4000; Ruta = /; Caduca = Martes, 19 de septiembre de 2017 21:11:36 GMT; HttpOnly Tipo de contenido: aplicación / json; juego de caracteres = utf-8 Longitud del contenido: 180 ETag: W / "b4-VNrmF4xNeHGeLrGehNZTQNwAaUQ" Fecha: lun, 18 de septiembre de 2017 21:11:36 GMT Conexión: mantener vivo
Además, puedo ver la cookie debajo Response Cookies
cuando inspecciono el tráfico usando la pestaña Red de las herramientas de desarrollo de Chrome. Sin embargo, no puedo ver que se establezca una cookie en la pestaña Aplicación debajo Storage/Cookies
. No veo ningún error de CORS, así que supongo que me falta algo más.
¿Alguna sugerencia?
Actualización I:
Estoy usando el módulo de solicitud en una aplicación React-Redux para emitir una solicitud a un /signin
punto final en el servidor. Para el servidor utilizo express.
Servidor expreso:
res.cookie ('token', 'xxx-xxx-xxx', {maxAge: 86400000, httpOnly: true, domain: 'localhost: 3000'})
Solicitud en navegador:
request.post ({uri: '/ signin', json: {userName: 'userOne', contraseña: '123456'}}, (err, response, body) => { // haciendo cosas })
Actualización II:
Estoy configurando encabezados de solicitud y respuesta ahora como loco, asegurándome de que estén presentes tanto en la solicitud como en la respuesta. A continuación se muestra una captura de pantalla. Fíjese en las cabeceras Access-Control-Allow-Credentials
, Access-Control-Allow-Headers
, Access-Control-Allow-Methods
y Access-Control-Allow-Origin
. Al observar el problema que encontré en el github de Axios , tengo la impresión de que todos los encabezados obligatorios ya están configurados. Sin embargo, todavía no hay suerte ...
fuente
request
módulo no está diseñado para su uso en el navegador. Axios parece haber hecho un gran trabajo hasta ahora. Ahora recibo tanto el encabezado:Access-Control-Allow-Credentials:true
comoAccess-Control-Allow-Origin:http://localhost:3000
(usado para habilitar CORS). Esto parece correcto, pero elSet-Cookie
encabezado no hace nada ...{ withCredentials: true }
hecho es requerido por el lado de Axios, los encabezados del servidor también deben revisarse cuidadosamente (consulte stackoverflow.com/a/48231372/488666 )Respuestas:
Qué necesitas hacer
Para permitir recibir y enviar cookies mediante una solicitud CORS con éxito, haga lo siguiente.
Back-end (servidor): establezca el
Access-Control-Allow-Credentials
valor del encabezado HTTP entrue
. Además, asegúrese de que los encabezados HTTPAccess-Control-Allow-Origin
yAccess-Control-Allow-Headers
estén configurados y no con un comodín*
.Para obtener más información sobre cómo configurar CORS en express js, lea los documentos aquí
Front-end (cliente): establezca la
XMLHttpRequest.withCredentials
marca entrue
, esto se puede lograr de diferentes maneras según la biblioteca de solicitud-respuesta utilizada:jQuery 1.5.1
xhrFields: {withCredentials: true}
ES6 buscar ()
credentials: 'include'
axios :
withCredentials: true
O
Evite tener que usar CORS en combinación con cookies. Puede lograr esto con un proxy.
Si por alguna razón no lo evites. La solución está arriba.
Resultó que Chrome no configurará la cookie si el dominio contiene un puerto. Configurarlo para
localhost
(sin puerto) no es un problema. ¡Muchas gracias a Erwin por este consejo!fuente
localhost
verificar esto aquí: stackoverflow.com/a/1188145 y también esto puede ayudar en su caso ( stackoverflow.com/questions/50966861/… )Access-Control-Allow-Origin
un dominio explícito, no solo"*"
. Entonces sería la respuesta perfectaNota para el navegador Chrome lanzado en 2020.
Entonces, si su servidor backend no configura SameSite = None, Chrome usará SameSite = Lax de manera predeterminada y no usará esta cookie con solicitudes {withCredentials: true}.
Más información https://www.chromium.org/updates/same-site .
Los desarrolladores de Firefox y Edge también quieren lanzar esta función en el futuro.
Especificaciones encontradas aquí: https://tools.ietf.org/html/draft-west-cookie-incrementalism-01#page-8
fuente
Para que el cliente pueda leer cookies de solicitudes de origen cruzado, debe tener:
Todas las respuestas del servidor deben tener lo siguiente en su encabezado:
Access-Control-Allow-Credentials: true
El cliente debe enviar todas las solicitudes con la
withCredentials: true
opciónEn mi implementación con Angular 7 y Spring Boot, lo logré con lo siguiente:
Lado del servidor:
La
origins = "http://my-cross-origin-url.com"
parte se agregaráAccess-Control-Allow-Origin: http://my-cross-origin-url.com
al encabezado de respuesta de cada servidorLa
allowCredentials = "true"
parte se agregaráAccess-Control-Allow-Credentials: true
al encabezado de respuesta de cada servidor, que es lo que necesitamos para que el cliente lea las cookies.Lado del cliente:
Con esta clase, en realidad, inyecta cosas adicionales a todas sus solicitudes.
La primera parte
req = req.clone({ withCredentials: true });
, es lo que necesita para poder enviar cada solicitud conwithCredentials: true
opción. Esto prácticamente significa que primero se enviará una solicitud de OPCIÓN, para que usted obtenga sus cookies y el token de autorización entre ellas, antes de enviar las solicitudes POST / PUT / DELETE reales, que necesitan este token adjunto (en el encabezado), en orden para que el servidor verifique y ejecute la solicitud.La segunda parte es la que maneja específicamente un token anti-CSRF para todas las solicitudes. Lo lee de la cookie cuando es necesario y lo escribe en el encabezado de cada solicitud.
El resultado deseado es algo como esto:
fuente
allowCredentials = "true"
en la@CrossOrigin
anotación me ayudó.La respuesta de Pim es muy útil. En mi caso, tengo que usar
Si es una fecha y hora, incluso si no está vencida, no enviará la cookie al backend:
Espero que sea útil para las personas futuras que puedan tener el mismo problema.
fuente
Para express, actualice su biblioteca express a
4.17.1
la última versión estable. Entonces;En CorsOption: establezca
origin
su URL de host local o su URL de producción de frontend y,credentials
portrue
ejemplo,Establecí mi origen dinámicamente usando el módulo config npm .
Luego, en res.cookie:
Para localhost: no es necesario para establecer y sameSite opción segura del todo, se puede establecer
httpOnly
quetrue
para http cookie para Prevenir XSS ataque y otras útiles opciones dependiendo de su caso de uso.Para el entorno de producción, debe establecer
sameSite
ennone
para la solicitud de origen cruzado ysecure
entrue
. Recuerde quesameSite
funciona con la última versión express solo como ahora y la última versión de Chrome solo configura las cookieshttps
, por lo tanto, la necesidad de una opción segura.Así es como hice el mío dinámico
fuente