Po zalogowaniu się za pośrednictwem $.ajax()
witryny próbuję wysłać drugie $.ajax()
żądanie do tej witryny - ale gdy sprawdzę nagłówki wysłane za pomocą FireBug, w żądaniu nie zostanie uwzględniony plik cookie sesji.
Co ja robię źle?
Po zalogowaniu się za pośrednictwem $.ajax()
witryny próbuję wysłać drugie $.ajax()
żądanie do tej witryny - ale gdy sprawdzę nagłówki wysłane za pomocą FireBug, w żądaniu nie zostanie uwzględniony plik cookie sesji.
Co ja robię źle?
Odpowiedzi:
Połączenia AJAX wysyłają pliki cookie tylko wtedy, gdy adres, do którego dzwonisz, znajduje się w tej samej domenie, co skrypt wywołujący.
Może to być problem między domenami.
Być może próbowałeś zadzwonić na adres URL z www.domain-a.com
włączonego skryptu wywołującego www.domain-b.com
(innymi słowy: nawiązałeś połączenie między domenami, w którym to przypadku przeglądarka nie wyśle żadnych plików cookie w celu ochrony Twojej prywatności).
W takim przypadku masz następujące opcje:
Cieszę się, że to pomogło choć trochę.
path=/something
i poprosisz o stronę, /another
plik cookie nie zostanie wysłany. Gdy poprosisz o stronę, /something
plik cookie zostanie wysłany zgodnie z oczekiwaniami. Więc sprawdź kod, który ustawia ciasteczko.
Działam w scenariuszu między domenami. Podczas logowania serwer zdalny zwraca nagłówek Set-Cookie wraz z Access-Control-Allow-Credentials
ustawieniem na true.
Następne wywołanie ajax do zdalnego serwera powinno użyć tego pliku cookie.
CORS Access-Control-Allow-Credentials
umożliwia rejestrowanie w wielu domenach. Sprawdź https://developer.mozilla.org/En/HTTP_access_control dla przykładów.
Dla mnie wygląda to na błąd w JQuery (lub przynajmniej w przyszłej wersji).
AKTUALIZACJA:
Pliki cookie nie są ustawiane automatycznie na podstawie odpowiedzi AJAX (cytowanie: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/ )
Dlaczego?
Nie można uzyskać wartości pliku cookie z odpowiedzi, aby ustawić go ręcznie ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader )
Jestem zmieszany..
Powinien istnieć sposób jquery.ajax()
na ustawienie XMLHttpRequest.withCredentials = "true"
parametru.
ODPOWIEDŹ:
Powinieneś użyć xhrFields
param z http://api.jquery.com/jQuery.ajax/
Przykład w dokumentacji to:
$.ajax({
url: a_cross_domain_url,
xhrFields: {
withCredentials: true
}
});
Ważne jest również, aby serwer poprawnie odpowiedział na to żądanie. Skopiuj tutaj świetne komentarze z @ Frédéric i @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: *
Więc kiedy prośba jest:
Origin: http://foo.example
Cookie: pageAccess=2
Serwer powinien odpowiedzieć:
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
[payload]
W przeciwnym razie ładunek nie zostanie zwrócony do skryptu. Zobacz: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials
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/…
Za pomocą
xhrFields: { withCredentials:true }
w ramach mojego wywołania jQuery ajax było tylko częścią rozwiązania. Musiałem także zwrócić nagłówki w odpowiedzi OPTIONS z mojego zasobu:
Access-Control-Allow-Origin : http://www.wombling.com
Access-Control-Allow-Credentials : true
Ważne było, aby tylko jeden dozwolony „początek” był w nagłówku odpowiedzi wywołania OPTIONS, a nie „*”. Osiągnąłem to, czytając pochodzenie z żądania i wypełniając je z powrotem w odpowiedzi - prawdopodobnie obchodząc pierwotny powód ograniczenia, ale w moim przypadku bezpieczeństwo nie jest najważniejsze.
Pomyślałem, że warto wyraźnie wspomnieć o wymogu tylko jednego źródła, ponieważ standard W3C pozwala na listę oddzieloną spacjami - ale Chrome nie! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB bit „w praktyce”.
Umieść to w swojej funkcji init:
$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
To będzie działać.
Istnieje już wiele dobrych odpowiedzi na to pytanie, ale pomyślałem, że pomocne może być wyjaśnienie przypadku, w którym można oczekiwać, że sesyjny plik cookie zostanie wysłany, ponieważ domena cookie jest zgodna, ale nie zostanie wysłany, ponieważ żądanie AJAX jest przeniesiony do innej subdomeny. W tym przypadku mam plik cookie przypisany do domeny * .mydomain.com i chcę, aby został on uwzględniony w żądaniu AJAX do pliku different.mydomain.com ”. Domyślnie plik cookie nie jest wysyłany. Nie musisz wyłączać HTTPONLY w pliku cookie sesji, aby rozwiązać ten problem. Musisz tylko zrobić to, co sugeruje wombling ( https://stackoverflow.com/a/23660618/545223 ) i wykonać następujące czynności.
1) Dodaj następujące elementy do żądania ajax.
xhrFields: { withCredentials:true }
2) Dodaj do nagłówków odpowiedzi następujące zasoby w różnych subdomenach.
Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true
Po wypróbowaniu innych rozwiązań i wciąż niedziałaniu, dowiedziałem się, jaki jest problem w moim przypadku. Zmieniłem contentType z „application / json” na „text / plain”.
$.ajax(fullUrl, {
type: "GET",
contentType: "text/plain",
xhrFields: {
withCredentials: true
},
crossDomain: true
});
Miałem ten sam problem i przeprowadzając kilka kontroli, mój skrypt po prostu nie otrzymywał pliku cookie sessionid.
Zorientowałem się, patrząc na wartość cookie sessionid w przeglądarce, że mój framework (Django) przekazuje cookie sessionid z HttpOnly jako domyślną. Oznaczało to, że skrypty nie miały dostępu do wartości sessionid i dlatego nie przekazywały jej wraz z żądaniami. To śmieszne, że HttpOnly byłby wartością domyślną, gdy tak wiele rzeczy używa Ajax, które wymagałyby ograniczenia dostępu.
Aby to naprawić, zmieniłem ustawienie (SESSION_COOKIE_HTTPONLY = False), ale w innych przypadkach może to być flaga „HttpOnly” na ścieżce pliku cookie
Jeśli localhost
programujesz na serwerze lokalnym lub jest to port, taki jak localhost:8080
oprócz kroków opisanych w powyższych odpowiedziach, musisz także upewnić się, że nie przekazujesz wartości domeny w nagłówku Set-Cookie.
Nie można ustawić domeny localhost
w nagłówku Set-Cookie - to nieprawda - po prostu pomiń domenę.
Zobacz Pliki cookie na localhost z jawną domeną i Dlaczego asp.net nie tworzy plików cookie na localhost?
Tylko moje 2 centy za ustawienie problemu z ciasteczkami PHPSESSID na localhost i w środowisku deweloperskim. Wykonuję wywołanie AJAX do punktu końcowego interfejsu API REST na locahost. Powiedz, że jego adres to mysite.localhost/api/member/login/
(virtal host w moim środowisku programistycznym).
Kiedy przesyłam to żądanie do Listonosza , wszystko idzie dobrze, a odpowiedź PHPSESSID jest ustawiona.
Kiedy żądam tego punktu końcowego za pośrednictwem AJAX ze strony proxy Browsersync (np. Z 122.133.1.110:3000/test/api/login.php
wiersza adresu mojej przeglądarki sprawdź, czy domena jest inna niż mysite.localhost
) PHPSESSID nie pojawia się wśród plików cookie.
Kiedy mysite.localhost/test/api/login.php
wysyłam to żądanie bezpośrednio ze strony w tej samej domenie (tj. ) PHPSESSID jest w porządku.
Jest to więc problem dotyczący plików cookie pochodzących z różnych źródeł, jak wspomniano w odpowiedzi @flu powyżej
Dodanie mojego scenariusza i rozwiązania na wypadek, gdyby pomógł komuś innemu. Podobny przypadek napotkałem podczas używania interfejsów API RESTful. Mój serwer WWW obsługujący pliki HTML / Script / CSS i interfejsy API serwera aplikacji udostępniające były hostowane w tej samej domenie. Jednak ścieżka była inna.
serwer WWW - mojadomena / webpages /abc.html
używał abc.js, który ustawił plik cookie o nazwie mycookie
serwer aplikacji - moja_domena / webapis / nazwa_usługi.
do których wykonano połączenia API
Spodziewałem się pliku cookie w mojej domenie / webapis / nazwa_usługi i próbowałem go przeczytać, ale nie został wysłany. Po przeczytaniu komentarza z odpowiedzi sprawdziłem w narzędziu programistycznym przeglądarki, że ścieżka mycookie została ustawiona na „/ webpages ”, a zatem nie jest dostępna w zgłoszeniu serwisowym do
mojadomena / webapis / nazwa_usługi
Więc ustawiając ciasteczko z jquery, właśnie to zrobiłem -
$.cookie("mycookie","mayvalue",{**path:'/'**});
Być może nie w 100% odpowiadając na pytanie, ale natknąłem się na ten wątek, mając nadzieję na rozwiązanie problemu z sesją, gdy publikowanie w pliku ładuje plik z menedżera zasobów edytora innovastudio. Ostatecznie rozwiązanie było proste: mają Flash-Uploader. Wyłączanie tego (ustawienie
var flashUpload = false;
w pliku asset.php), a kontrolki ponownie zaczęły migać.
Ponieważ te problemy mogą być bardzo trudne do debugowania, odkryłem, że umieszczenie czegoś takiego jak poniżej w programie do przesyłania przesyła cię (cóż, w tym przypadku ja) na właściwą ścieżkę:
$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");
Zanurkowałem w dzienniku i szybko zauważyłem brakującą sesję, w której nie wysłano ciasteczka.
session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();
ten sposób dostaliby działający element