Perché il metodo .ajax () di jquery non invia il mio cookie di sessione?


338

Dopo aver effettuato l'accesso tramite $.ajax()un sito, sto cercando di inviare un secondo$.ajax() richiesta a quel sito, ma quando controllo le intestazioni inviate utilizzando FireBug, nella richiesta non viene incluso alcun cookie di sessione.

Che cosa sto facendo di sbagliato?


2
Il cookie di Ajax potrebbe venire dopo il cookie Web e FireBug potrebbe catturare il cookie della prima pagina.
Chris,

1
Non ho capito cosa intendi, ma posso dire se incollo l'URL della richiesta nella barra degli indirizzi del browser e controllo di nuovo Firebug, posso vedere il cookie in headres inviato al server. Qualche soluzione?
user345625

Quindi, penso che ajax gestirà anche lo stesso modo del browser
user345625

Qual è il codice che stai usando?
Dean Harding,

il browser creerà comunque i cookie impostati dal server durante una richiesta Ajax, jquery o altro. Hai verificato la risposta alla richiesta Ajax e verificato che i cookie siano tornati dal server per essere impostati? Potrebbe esserci un problema con il codice del server in modo tale che non stia nemmeno impostando il cookie, ecc.
David

Risposte:


218

Le chiamate AJAX inviano i cookie solo se l'URL che stai chiamando si trova nello stesso dominio dello script chiamante.

Questo potrebbe essere un problema tra domini.

Forse hai provato a chiamare un URL www.domain-a.commentre lo script di chiamata era attivo www.domain-b.com(in altre parole: hai effettuato una chiamata tra domini nel qual caso il browser non ha inviato alcun cookie per proteggere la tua privacy).

In questo caso le tue opzioni sono:

  • Scrivi un piccolo proxy che risiede sul dominio-b e inoltra le tue richieste al dominio-a. Il tuo browser ti permetterà di chiamare il proxy perché si trova sullo stesso server dello script chiamante.
    Questo proxy può quindi essere configurato da te per accettare un nome cookie e un parametro valore che può inviare al dominio-a. Ma per far funzionare tutto questo è necessario conoscere il nome del cookie e valutare il proprio server sul dominio-a vuole l'autenticazione.
  • Se stai recuperando oggetti JSON, prova invece a utilizzare una richiesta JSONP . jQuery supporta questi. Ma devi modificare il tuo servizio sul dominio, in modo che restituisca risposte JSONP valide.

Sono contento che ciò abbia aiutato anche un po '.


19
Vale anche la pena notare che i cookie possono essere impostati su un percorso specifico, quindi se il cookie è stato impostato con path=/somethinge stai richiedendo la pagina, /anotheril cookie non verrà inviato. Quando richiedi la pagina /somethingil cookie verrà inviato come previsto. Quindi controlla anche il codice che imposta il cookie.
styfle

2
una richiesta jsonp invia coockies?
albanx,

1
@albanx Sì, se sono impostati i requisiti che ho citato. È solo una normale richiesta come qualsiasi altra e come tale invia cookie.
influenza

1
@albanx questa altra domanda correlata include un esempio di come fare quella richiesta JSONP con i cookie personalizzati
AntonioHerraizS

4
Secondo JSONP su Wikipedia> questo approccio è stato abbandonato a favore del CORS
Peter Dotchev,

388

Opero in uno scenario interdominio. Durante l'accesso, il server remoto restituisce l'intestazione Set-Cookie insieme a Access-Control-Allow-Credentialsset su true.

La prossima chiamata ajax al server remoto dovrebbe utilizzare questo cookie.

CORS Access-Control-Allow-Credentialsè lì per consentire la registrazione tra domini. Controlla https://developer.mozilla.org/En/HTTP_access_control per esempi.

Per me sembra un bug in JQuery (o almeno una funzionalità nella prossima versione).

AGGIORNARE:

  1. I cookie non vengono impostati automaticamente dalla risposta AJAX (citazione: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/ )

    Perché?

  2. Non è possibile ottenere il valore del cookie dalla risposta per impostarlo manualmente ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader )

    Non ho capito bene..

    Dovrebbe esistere un modo per chiedere jquery.ajax()di impostare il XMLHttpRequest.withCredentials = "true"parametro.

RISPOSTA: è necessario utilizzare il xhrFieldsparametro http://api.jquery.com/jQuery.ajax/

L'esempio nella documentazione è:

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
});

È anche importante che il server risponda correttamente a questa richiesta. Copia qui i grandi commenti di @ Frédéric e @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: *

Quindi quando la richiesta è:

Origin: http://foo.example
Cookie: pageAccess=2

Il server dovrebbe rispondere con:

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true

[payload]

Altrimenti il ​​payload non verrà restituito allo script. Vedi: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials


8
Grande ! Aggiungo per usare questa + impostazione dell'intestazione Access-Control-Allow-Credentials su true sul lato server
Frédéric

e dove devo impostare quelle credenziali?, presso l'autorizzazione intestazione?, presso l'organismo di richiesta?
Francisco Corrales Morales,

3
Grazie per la risposta :) solo una breve aggiunta, potrebbe valere la pena menzionare 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

Niente di tutto questo ha funzionato per me, sfortunatamente. Se eseguo la stessa richiesta da AngularJS funziona, ma da jQuery, anche con questi suggerimenti il ​​cookie di sessione non viene passato. (jQuery v2.1.1)
geoidesic

(OO) Mi hai salvato da varie ore dolorose. Che risposta perfetta! Grazie! Ho dovuto aggiungerli nella .htaccess di root pubblica del mio sito Web: <IfModule mod_headers.c> Set di intestazioni Access-Control-Allow-Origin " localhost " Set di intestazioni Access-Control-Allow-Credentials "true" </IfModule>
Vinay Vissh

48

utilizzando

xhrFields: { withCredentials:true }

come parte della mia chiamata ajax jQuery era solo una parte della soluzione. Avevo anche bisogno di avere le intestazioni restituite nella risposta OPTIONS dalla mia risorsa:

Access-Control-Allow-Origin : http://www.wombling.com
Access-Control-Allow-Credentials : true

Era importante che solo una consentisse "origine" era nell'intestazione della risposta della chiamata OPTIONS e non "*". Ho raggiunto questo obiettivo leggendo l'origine della richiesta e inserendola nuovamente nella risposta, probabilmente eludendo il motivo originale della restrizione, ma nel mio caso d'uso la sicurezza non è fondamentale.

Ho pensato che valesse la pena menzionare esplicitamente il requisito di una sola origine, poiché lo standard W3C consente un elenco separato da spazi, ma Chrome no! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB il bit "in pratica".


41

Metti questo nella tua funzione init:

$.ajaxSetup({
  xhrFields: {
    withCredentials: true
  }
});

Funzionerà.


1
Mi hai salvato la giornata! A livello di metodo conCredentials non ha funzionato per me. Ma a livello globale, finalmente funziona! Grazie.
Paulius Matulionis,

fai attenzione, perché invierà i cookie a tutte le richieste, etere per altri domini (che non è previsto e non soddisfa la richiesta richiede Access-Control-Allow-Credentials)
gdbdable

12

Ci sono già molte buone risposte a questa domanda, ma ho pensato che potrebbe essere utile chiarire il caso in cui ti aspetteresti che il cookie di sessione venga inviato perché il dominio del cookie corrisponde, ma non viene inviato perché la richiesta AJAX è essere creato per un sottodominio diverso. In questo caso, ho un cookie assegnato al dominio * .mydomain.com e desidero che sia incluso in una richiesta AJAX a different.mydomain.com ". Per impostazione predefinita, il cookie non viene inviato. Non è necessario disabilitare HTTPONLY sul cookie di sessione per risolvere questo problema. È sufficiente fare ciò che il wombling ha suggerito ( https://stackoverflow.com/a/23660618/545223 ) e procedere come segue.

1) Aggiungi quanto segue alla tua richiesta Ajax.

xhrFields: { withCredentials:true }

2) Aggiungi quanto segue alle intestazioni di risposta per le risorse nel sottodominio diverso.

Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true

7

Dopo aver provato le altre soluzioni e ancora non riuscendo a farlo funzionare, ho scoperto quale fosse il problema nel mio caso. Ho cambiato contentType da "application / json" a "text / plain".

$.ajax(fullUrl, {
    type: "GET",
    contentType: "text/plain",
    xhrFields: {
         withCredentials: true
    },
    crossDomain: true
});

4

Stavo avendo lo stesso problema e facendo alcuni controlli il mio script non stava semplicemente ricevendo il cookie sessionid.

Ho scoperto osservando il valore del cookie sessionid nel browser che il mio framework (Django) stava passando il cookie sessionid con HttpOnly come predefinito. Ciò significava che gli script non avevano accesso al valore sessionid e quindi non lo passavano insieme alle richieste. È ridicolo che HttpOnly sia il valore predefinito quando così tante cose usano Ajax che richiederebbe restrizioni di accesso.

Per risolvere questo problema ho modificato un'impostazione (SESSION_COOKIE_HTTPONLY = False) ma in altri casi potrebbe essere un flag "HttpOnly" sul percorso del cookie


2
Non farlo. Consente l'accesso dello script lato client al cookie di sessione che è il vettore di attacco XSS più comune. owasp.org/index.php/HttpOnly
Jason Elkin


0

Solo i miei 2 centesimi sull'impostazione del problema con i cookie PHPSESSID su localhost e in ambiente di sviluppo. Eseguo la chiamata AJAX al mio endpoint API REST sul locahost. Supponiamo che il suo indirizzo sia mysite.localhost/api/member/login/(host virtuoso nel mio ambiente di sviluppo).

  • Quando faccio questa richiesta su Postman , le cose vanno bene e PHPSESSID è impostato con la risposta.

  • Quando richiedo questo endpoint tramite AJAX dalla pagina proxy di Browsersync (ad es. Dalla 122.133.1.110:3000/test/api/login.phpriga dell'indirizzo del mio browser, vedo che il dominio è diverso rispetto a mysite.localhost) PHPSESSID non viene visualizzato tra i cookie.

  • Quando faccio questa richiesta direttamente dalla pagina sullo stesso dominio (cioè mysite.localhost/test/api/login.php) PHPSESSID è impostato correttamente.

Quindi si tratta di un problema relativo ai cookie di richiesta di origine incrociata, come indicato nella risposta @flu sopra


0

Aggiungere il mio scenario e la mia soluzione nel caso in cui aiuti qualcun altro. Ho riscontrato un caso simile durante l'utilizzo delle API RESTful. Il mio server Web che ospita file HTML / Script / CSS e il server delle applicazioni che espongono le API sono stati ospitati sullo stesso dominio. Tuttavia, il percorso era diverso.

web server - miodominio / pagine web /abc.html

usato abc.js che imposta cookie chiamato mycookie

server app - miodominio / webapis / nome servizio.

a cui sono state fatte le chiamate API

Mi aspettavo il cookie in miodominio / webapis / nome servizio e ho provato a leggerlo ma non è stato inviato. Dopo aver letto il commento dalla risposta, ho verificato nello strumento di sviluppo del browser che il percorso di mycookie era impostato su "/ pagine web " e quindi non disponibile nella chiamata di servizio a

miodominio / webapis / nome servizio

Quindi durante l'impostazione dei cookie da jquery, questo è quello che ho fatto -

$.cookie("mycookie","mayvalue",{**path:'/'**});

-5

Forse non rispondevo al 100% alla domanda, ma mi sono imbattuto in questo thread nella speranza di risolvere un problema di sessione durante la pubblicazione di un fileupload dal gestore delle risorse dell'editor innovastudio. Alla fine la soluzione era semplice: hanno un flash-uploader. Disabilitando quello (impostazione

var flashUpload = false;   

in asset.php) e le luci hanno ricominciato a lampeggiare.

Dato che questi problemi possono essere molto difficili da debug, ho scoperto che mettere qualcosa di simile nel gestore del caricamento ti metterà sulla strada giusta (beh, io in questo caso):

$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");

Un tuffo nel registro e ho individuato rapidamente la sessione mancante, dove non è stato inviato alcun cookie.


Non credo che l'esempio sopra funzionerebbe, perché quando non ci sono cookie di sessione, quale sarebbe il valore di $ sn? (uno casuale, o forse nullo), in alternativa gli utenti potrebbero impostare session_name da un valore GET, ad esempio in session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();questo modo, otterrebbero un lavoro funzionante
Steel Brain,

Questo è esattamente il modo in cui ho riscontrato il problema: nessuna sessione durante la pubblicazione da questo uploader flash. Poiché l'utilizzo di un identificatore di sessione variabile GET è una cattiva idea e il cookie non funzionava, l'ho buttato fuori. Chi se ne frega, il flash è comunque un ricordo del passato.
Ellert van Koperen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.