¿Por qué el método .ajax () de jquery no envía mi cookie de sesión?
338
Después de iniciar sesión en $.ajax()un sitio, intento enviar una segunda $.ajax()solicitud a ese sitio, pero cuando verifico los encabezados enviados con FireBug, no se incluye ninguna cookie de sesión en la solicitud.
La cookie de ajax puede aparecer después de la cookie web y FireBug puede capturar la cookie de la primera página.
Chris
1
No entendí lo que quieres decir, pero puedo decir que si pego la URL de solicitud en la barra de direcciones del navegador y verifico nuevamente Firebug, puedo ver la cookie en los encabezados enviados al servidor. ¿Alguna solución?
user345625
Entonces, creo que ajax también se manejará de la misma manera que lo hace el navegador
usuario345625
¿Cuál es el código que estás usando?
Dean Harding
el navegador seguirá creando cookies establecidas por el servidor durante una solicitud ajax, jquery o de otra manera. ¿Verificó la respuesta a la solicitud de ajax y se aseguró de que las cookies regresaron del servidor para ser configuradas? Podría haber un problema con el código del servidor de tal manera que ni siquiera está configurando la cookie, etc.
David
Respuestas:
218
Las llamadas AJAX solo envían cookies si la url a la que llama está en el mismo dominio que su script de llamada.
Esto puede ser un problema de dominio cruzado.
Tal vez trató de llamar a una URL desde www.domain-a.comque su script de llamada estaba activado www.domain-b.com(en otras palabras: realizó una llamada entre dominios, en cuyo caso el navegador no enviará ninguna cookie para proteger su privacidad).
En este caso, sus opciones son:
Escriba un pequeño proxy que resida en el dominio-b y reenvíe sus solicitudes al dominio-a. Su navegador le permitirá llamar al proxy porque está en el mismo servidor que el script de llamada. Usted puede configurar este proxy para que acepte un nombre de cookie y un parámetro de valor que puede enviar al dominio-a. Pero para que esto funcione, necesita saber el nombre de la cookie y valorar su servidor en el dominio-a quiere autenticación.
Si está buscando objetos JSON, intente utilizar una solicitud JSONP en su lugar. jQuery es compatible con estos. Pero debe alterar su servicio en el dominio-a para que devuelva respuestas JSONP válidas.
También vale la pena señalar que las cookies se pueden establecer en una ruta específica, por lo que si su cookie se configuró path=/somethingy está solicitando la página/another , la cookie no se enviará. Cuando solicite la página, /somethingla cookie se enviará como se esperaba. Así que verifique también el código que establece la cookie.
styfle
2
¿Una solicitud de JSONP envía coockies?
albanx
1
@albanx Sí, si se establecen los requisitos que mencioné. Es solo una solicitud normal como cualquier otra y, como tal, envía cookies.
gripe
1
@albanx esta otra pregunta relacionada incluye un ejemplo de cómo hacer esa solicitud JSONP con cookies personalizadas
AntonioHerraizS
44
De acuerdo con JSONP en Wikipedia> este enfoque fue abandonado a favor de CORS
Peter Dotchev
388
Estoy operando en un escenario de dominio cruzado. Durante el inicio de sesión, el servidor remoto devuelve el encabezado Set-Cookie junto con Access-Control-Allow-Credentialsset a true.
La próxima llamada ajax al servidor remoto debe usar esta cookie.
También es importante que el servidor responda correctamente a esta solicitud. Copiando aquí excelentes comentarios de @ Frédéric y @Pebbl:
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *
Excelente ! Agrego para usar este + conjunto de encabezado Access-Control-Allow-Credentials a verdadero en el lado del servidor
Frédéric
¿y dónde configuro esas Credenciales ?, ¿en la Autorización de encabezado ?, ¿en el cuerpo de la solicitud?
Francisco Corrales Morales
3
Gracias por la respuesta :) solo una adición rápida, puede valer la pena mencionar Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *developer.mozilla.org/en-US/docs/Web/HTTP/…
Pebbl
Nada de esto me funcionó desafortunadamente. Si ejecuto la misma solicitud de AngularJS, funciona, pero desde jQuery, incluso con estas sugerencias, la cookie de sesión no se pasa. (jQuery v2.1.1)
geodésico
(OO) Me salvaste de varias horas dolorosas. ¡Qué respuesta perfecta! ¡Gracias! Necesitaba agregarlos en la raíz pública .htaccess de mi sitio web: <IfModule mod_headers.c> Conjunto de encabezado Access-Control-Allow-Origin " localhost " Conjunto de encabezado Access-Control-Allow-Credentials "true" </IfModule>
Vinay Vissh
48
Utilizando
xhrFields:{ withCredentials:true}
Como parte de mi llamada jQuery ajax fue solo parte de la solución. También necesitaba que me devolvieran los encabezados en la respuesta OPTIONS de mi recurso:
Era importante que solo un "origen" permitido estuviera en el encabezado de respuesta de la llamada OPTIONS y no "*". Lo logré leyendo el origen de la solicitud y llenándolo nuevamente a la respuesta, probablemente eludiendo la razón original de la restricción, pero en mi caso de uso la seguridad no es primordial.
¡Salvaste mi día! En el nivel de método con credenciales no funcionó para mí. ¡Pero globalmente como este finalmente funciona! Gracias.
Paulius Matulionis
tenga cuidado con esto, ya que enviará cookies a todas las solicitudes, éter para otros dominios (que no se espera esto y falla la solicitud por requerir Access-Control-Allow-Credentials)
gdbdable
12
Ya hay muchas buenas respuestas a esta pregunta, pero pensé que podría ser útil aclarar el caso en el que esperaría que se envíe la cookie de sesión porque el dominio de la cookie coincide, pero no se envía porque la solicitud AJAX es siendo hecho a un subdominio diferente. En este caso, tengo una cookie que está asignada al dominio * .midominio.com , y deseo que se incluya en una solicitud AJAX a different.mydomain.com ". Por defecto, la cookie no se envía. No necesita deshabilitar HTTPONLY en la cookie de sesión para resolver este problema. Solo necesita hacer lo que sugiere wombling ( https://stackoverflow.com/a/23660618/545223 ) y hacer lo siguiente.
1) Agregue lo siguiente a su solicitud de ajax.
xhrFields:{ withCredentials:true}
2) Agregue lo siguiente a sus encabezados de respuesta para los recursos en los diferentes subdominios.
Después de probar las otras soluciones y aún no lograr que funcionara, descubrí cuál era el problema en mi caso. Cambié contentType de "application / json" a "text / plain".
Estaba teniendo el mismo problema y haciendo algunas comprobaciones mi script simplemente no estaba recibiendo la cookie sessionid.
Al observar el valor de la cookie de sessionid en el navegador, descubrí que mi framework (Django) estaba pasando la cookie de sessionid con HttpOnly como predeterminado. Esto significaba que los scripts no tenían acceso al valor de sessionid y, por lo tanto, no lo pasaban junto con las solicitudes. Es ridículo que HttpOnly sea el valor predeterminado cuando tantas cosas usan Ajax que requerirían restricción de acceso.
Para solucionar esto, cambié una configuración (SESSION_COOKIE_HTTPONLY = False) pero en otros casos puede ser un indicador "HttpOnly" en la ruta de la cookie
No hagas esto. Permite el acceso del script del lado del cliente a la cookie de sesión, que es el vector de ataque XSS más común. owasp.org/index.php/HttpOnly
Jason Elkin
1
Si está desarrollando en localhosto un puerto en localhost como localhost:8080, además de los pasos descritos en las respuestas anteriores, también debe asegurarse de no pasar un valor de dominio en el encabezado Set-Cookie.
No puede establecer el dominio localhosten el encabezado Set-Cookie, eso es incorrecto, solo omita el dominio.
Solo mis 2 centavos para configurar el problema de cookies PHPSESSID cuando estoy en localhost y en un entorno de desarrollo. Realizo la llamada AJAX a mi punto final API REST en el host local. Digamos que su dirección es mysite.localhost/api/member/login/(host virtual en mi entorno de desarrollo).
Cuando hago esta solicitud en Postman , las cosas van bien y PHPSESSID se configura con la respuesta.
Cuando solicito este punto final a través de AJAX desde la página proxy de Browsersync (por ejemplo, 122.133.1.110:3000/test/api/login.phpen la línea de dirección de mi navegador, veo que el dominio es diferente vs mysite.localhost) PHPSESSID no aparece entre las cookies.
Cuando realizo esta solicitud directamente desde la página en el mismo dominio (es decir mysite.localhost/test/api/login.php), PHPSESSID está configurado correctamente.
Entonces, este es un problema de cookies de solicitud de origen de origen cruzado como se menciona en la respuesta @flu anterior
Agregar mi escenario y solución en caso de que ayude a alguien más. Encontré un caso similar al usar API RESTful. Mi servidor web que alojaba archivos HTML / Script / CSS y el servidor de aplicaciones que exponía API estaban alojados en el mismo dominio. Sin embargo, el camino era diferente.
servidor web: midominio / páginas web /abc.html
utiliza abc.js que establece la cookie llamada mycookie
servidor de aplicaciones: midominio / webapis / servicename.
a lo que se hicieron llamadas API
Esperaba la cookie en mydomain / webapis / servicename e intenté leerla pero no se estaba enviando. Después de leer el comentario de la respuesta, verifiqué en la herramienta de desarrollo del navegador que la ruta de mycookie estaba configurada en "/ páginas web " y, por lo tanto, no estaba disponible en la llamada de servicio para
midominio / webapis / servicename
Entonces, al configurar la cookie desde jquery, esto es lo que hice:
Tal vez no responda al 100% a la pregunta, pero me topé con este hilo con la esperanza de resolver un problema de sesión cuando publico una carga de archivo desde el administrador de activos del editor innovastudio. Finalmente, la solución fue simple: tienen un cargador de flash. Deshabilitar eso (configuración
var flashUpload =false;
en asset.php) y las luces comenzaron a parpadear nuevamente.
Como estos problemas pueden ser muy difíciles de depurar, descubrí que poner algo como lo siguiente en el controlador de carga lo colocará (en este caso, a mí) en el camino correcto:
$sn=session_name();
error_log("session_name: $sn ");if(isset($_GET[$sn])) error_log("session as GET param");if(isset($_POST[$sn])) error_log("session as POST param");if(isset($_COOKIE[$sn])) error_log("session as Cookie");if(isset($PHPSESSID)) error_log("session as Global");
Me sumergí en el registro y rápidamente vi la sesión perdida, donde no se envió ninguna cookie.
No creo que el ejemplo anterior funcione, porque cuando no hay una cookie de sesión, ¿cuál sería el valor de $ sn? (uno aleatorio, o tal vez nulo), alternativamente, los usuarios podrían establecer session_name a partir de un valor GET, por ejemplo, de session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();esta manera, obtendrían algo que funciona
Steel Brain
Así es exactamente como encontré el problema: no hay sesión al publicar desde este cargador flash. Como usar un identificador de sesión variable GET es una mala idea, y la cookie no funcionaba, la descarté. A quién le importa, de todos modos, el flash es cosa del pasado.
Respuestas:
Las llamadas AJAX solo envían cookies si la url a la que llama está en el mismo dominio que su script de llamada.
Esto puede ser un problema de dominio cruzado.
Tal vez trató de llamar a una URL desde
www.domain-a.com
que su script de llamada estaba activadowww.domain-b.com
(en otras palabras: realizó una llamada entre dominios, en cuyo caso el navegador no enviará ninguna cookie para proteger su privacidad).En este caso, sus opciones son:
Usted puede configurar este proxy para que acepte un nombre de cookie y un parámetro de valor que puede enviar al dominio-a. Pero para que esto funcione, necesita saber el nombre de la cookie y valorar su servidor en el dominio-a quiere autenticación.
Me alegro si eso ayudó incluso un poco.
fuente
path=/something
y está solicitando la página/another
, la cookie no se enviará. Cuando solicite la página,/something
la cookie se enviará como se esperaba. Así que verifique también el código que establece la cookie.Estoy operando en un escenario de dominio cruzado. Durante el inicio de sesión, el servidor remoto devuelve el encabezado Set-Cookie junto con
Access-Control-Allow-Credentials
set a true.La próxima llamada ajax al servidor remoto debe usar esta cookie.
CORS
Access-Control-Allow-Credentials
está ahí para permitir el registro entre dominios. Consulte https://developer.mozilla.org/En/HTTP_access_control para ver ejemplos.Para mí, parece un error en JQuery (o al menos característica en la próxima versión).
ACTUALIZAR:
Las cookies no se configuran automáticamente a partir de la respuesta AJAX (cita: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/ )
¿Por qué?
No puede obtener el valor de la cookie de la respuesta para configurarla manualmente ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader )
Estoy confundido..
Debería existir una manera de pedir
jquery.ajax()
establecer elXMLHttpRequest.withCredentials = "true"
parámetro.RESPUESTA: Debes usar el
xhrFields
parámetro de http://api.jquery.com/jQuery.ajax/El ejemplo en la documentación es:
También es importante que el servidor responda correctamente a esta solicitud. Copiando aquí excelentes comentarios de @ Frédéric y @Pebbl:
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *
Entonces, cuando la solicitud es:
El servidor debe responder con:
De lo contrario, la carga útil no se devolverá al script. Ver: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials
fuente
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. The above example would fail if the header was wildcarded as: Access-Control-Allow-Origin: *
developer.mozilla.org/en-US/docs/Web/HTTP/…Utilizando
Como parte de mi llamada jQuery ajax fue solo parte de la solución. También necesitaba que me devolvieran los encabezados en la respuesta OPTIONS de mi recurso:
Era importante que solo un "origen" permitido estuviera en el encabezado de respuesta de la llamada OPTIONS y no "*". Lo logré leyendo el origen de la solicitud y llenándolo nuevamente a la respuesta, probablemente eludiendo la razón original de la restricción, pero en mi caso de uso la seguridad no es primordial.
Pensé que valía la pena mencionar explícitamente el requisito de un solo origen, ya que el estándar W3C permite una lista separada por espacios, ¡pero Chrome no lo hace! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB el bit "en la práctica".
fuente
Pon esto en tu función init:
Funcionará.
fuente
Ya hay muchas buenas respuestas a esta pregunta, pero pensé que podría ser útil aclarar el caso en el que esperaría que se envíe la cookie de sesión porque el dominio de la cookie coincide, pero no se envía porque la solicitud AJAX es siendo hecho a un subdominio diferente. En este caso, tengo una cookie que está asignada al dominio * .midominio.com , y deseo que se incluya en una solicitud AJAX a different.mydomain.com ". Por defecto, la cookie no se envía. No necesita deshabilitar HTTPONLY en la cookie de sesión para resolver este problema. Solo necesita hacer lo que sugiere wombling ( https://stackoverflow.com/a/23660618/545223 ) y hacer lo siguiente.
1) Agregue lo siguiente a su solicitud de ajax.
2) Agregue lo siguiente a sus encabezados de respuesta para los recursos en los diferentes subdominios.
fuente
Después de probar las otras soluciones y aún no lograr que funcionara, descubrí cuál era el problema en mi caso. Cambié contentType de "application / json" a "text / plain".
fuente
Estaba teniendo el mismo problema y haciendo algunas comprobaciones mi script simplemente no estaba recibiendo la cookie sessionid.
Al observar el valor de la cookie de sessionid en el navegador, descubrí que mi framework (Django) estaba pasando la cookie de sessionid con HttpOnly como predeterminado. Esto significaba que los scripts no tenían acceso al valor de sessionid y, por lo tanto, no lo pasaban junto con las solicitudes. Es ridículo que HttpOnly sea el valor predeterminado cuando tantas cosas usan Ajax que requerirían restricción de acceso.
Para solucionar esto, cambié una configuración (SESSION_COOKIE_HTTPONLY = False) pero en otros casos puede ser un indicador "HttpOnly" en la ruta de la cookie
fuente
Si está desarrollando en
localhost
o un puerto en localhost comolocalhost:8080
, además de los pasos descritos en las respuestas anteriores, también debe asegurarse de no pasar un valor de dominio en el encabezado Set-Cookie.No puede establecer el dominio
localhost
en el encabezado Set-Cookie, eso es incorrecto, solo omita el dominio.Vea Cookies en localhost con dominio explícito y ¿Por qué asp.net no crea cookies en localhost?
fuente
Solo mis 2 centavos para configurar el problema de cookies PHPSESSID cuando estoy en localhost y en un entorno de desarrollo. Realizo la llamada AJAX a mi punto final API REST en el host local. Digamos que su dirección es
mysite.localhost/api/member/login/
(host virtual en mi entorno de desarrollo).Cuando hago esta solicitud en Postman , las cosas van bien y PHPSESSID se configura con la respuesta.
Cuando solicito este punto final a través de AJAX desde la página proxy de Browsersync (por ejemplo,
122.133.1.110:3000/test/api/login.php
en la línea de dirección de mi navegador, veo que el dominio es diferente vsmysite.localhost
) PHPSESSID no aparece entre las cookies.Cuando realizo esta solicitud directamente desde la página en el mismo dominio (es decir
mysite.localhost/test/api/login.php
), PHPSESSID está configurado correctamente.Entonces, este es un problema de cookies de solicitud de origen de origen cruzado como se menciona en la respuesta @flu anterior
fuente
Agregar mi escenario y solución en caso de que ayude a alguien más. Encontré un caso similar al usar API RESTful. Mi servidor web que alojaba archivos HTML / Script / CSS y el servidor de aplicaciones que exponía API estaban alojados en el mismo dominio. Sin embargo, el camino era diferente.
utiliza abc.js que establece la cookie llamada mycookie
a lo que se hicieron llamadas API
Esperaba la cookie en mydomain / webapis / servicename e intenté leerla pero no se estaba enviando. Después de leer el comentario de la respuesta, verifiqué en la herramienta de desarrollo del navegador que la ruta de mycookie estaba configurada en "/ páginas web " y, por lo tanto, no estaba disponible en la llamada de servicio para
Entonces, al configurar la cookie desde jquery, esto es lo que hice:
fuente
Tal vez no responda al 100% a la pregunta, pero me topé con este hilo con la esperanza de resolver un problema de sesión cuando publico una carga de archivo desde el administrador de activos del editor innovastudio. Finalmente, la solución fue simple: tienen un cargador de flash. Deshabilitar eso (configuración
en asset.php) y las luces comenzaron a parpadear nuevamente.
Como estos problemas pueden ser muy difíciles de depurar, descubrí que poner algo como lo siguiente en el controlador de carga lo colocará (en este caso, a mí) en el camino correcto:
Me sumergí en el registro y rápidamente vi la sesión perdida, donde no se envió ninguna cookie.
fuente
session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();
esta manera, obtendrían algo que funciona