¿Cómo compartir cookies de origen cruzado? Más específicamente, ¿cómo usar el Set-Cookieencabezado 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:4000en 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 Cookiescuando 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 /signinpunto 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-Methodsy 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


requestmó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:truecomoAccess-Control-Allow-Origin:http://localhost:3000(usado para habilitar CORS). Esto parece correcto, pero elSet-Cookieencabezado 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-Credentialsvalor del encabezado HTTP entrue. Además, asegúrese de que los encabezados HTTPAccess-Control-Allow-OriginyAccess-Control-Allow-Headersesté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.withCredentialsmarca 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: trueO
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
localhostverificar esto aquí: stackoverflow.com/a/1188145 y también esto puede ayudar en su caso ( stackoverflow.com/questions/50966861/… )Access-Control-Allow-Originun 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: trueEl cliente debe enviar todas las solicitudes con la
withCredentials: trueopció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.comal encabezado de respuesta de cada servidorLa
allowCredentials = "true"parte se agregaráAccess-Control-Allow-Credentials: trueal 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: trueopció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@CrossOriginanotació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.1la última versión estable. Entonces;En CorsOption: establezca
originsu URL de host local o su URL de producción de frontend y,credentialsportrueejemplo,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
httpOnlyquetruepara http cookie para Prevenir XSS ataque y otras útiles opciones dependiendo de su caso de uso.Para el entorno de producción, debe establecer
sameSiteennonepara la solicitud de origen cruzado ysecureentrue. Recuerde quesameSitefunciona 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