Jquery'nin .ajax () yöntemi neden oturum çerezimi göndermiyor?


338

$.ajax()Bir siteye giriş yaptıktan sonra , $.ajax()o siteye ikinci bir istek göndermeye çalışıyorum - ancak FireBug kullanarak gönderilen başlıkları kontrol ettiğimde, isteğe dahil olan bir oturum çerezi yok.

Neyi yanlış yapıyorum?


2
Ajax çerezleri web çerezinden sonra gelebilir ve FireBug ilk sayfa çerezini yakalayabilir.
Chris

1
Ne demek istediğini alamadım ama istek URL'sini tarayıcı adres çubuğuna yapıştırır ve Firebug'u tekrar kontrol edersem, sunucuya gönderilen başlıklarda çerezleri görebilirim. Herhangi bir çözüm var mı?
user345625

Yani, ben de ajax tarayıcı aynı şekilde ele alacağını düşünüyorum
user345625 20:05

Kullandığınız kod nedir?
Dean Harding

tarayıcı yine de ajax isteği, jquery veya başka bir şey sırasında sunucu tarafından ayarlanan çerezleri oluşturur. Ajax isteğine verilen yanıtı kontrol ettiniz ve çerezlerin ayarlanacak sunucudan geri döndüğünden emin misiniz? Sunucu kodu ile ilgili bir sorun olabilir, böylece çerez ayarlanamaz bile.
David

Yanıtlar:


218

AJAX çağrıları, yalnızca aradığınız url, çağrı komut dosyanızla aynı etki alanındaysa Çerez gönderir.

Bu bir Web Alanları Arası Sorun olabilir.

Belki www.domain-a.comarama komut dosyanız açıkken bir url'yi aramayı denediniz www.domain-b.com(Başka bir deyişle: Bir Alanlar Arası Arama yaptınız, bu durumda tarayıcı gizliliğinizi korumak için herhangi bir çerez göndermez).

Bu durumda seçenekleriniz:

  • Etki alanı-b'de bulunan ve isteklerinizi etki alanı-a'ya ileten küçük bir proxy yazın. Tarayıcınız, arama komut dosyasıyla aynı sunucuda olduğu için proxy'yi aramanıza izin verecektir.
    Bu proxy daha sonra tarafınızdan a-alanına gönderebileceği bir çerez adı ve değer parametresini kabul edecek şekilde yapılandırılabilir. Ancak bunun çalışması için çerezin adını bilmeniz ve sunucunuza alan adı a kimlik doğrulaması için değer vermeniz gerekir.
  • JSON nesneleri getiriyorsanız bunun yerine bir JSONP isteği kullanmayı deneyin . jQuery bunları destekler. Ancak geçerli JSONP yanıtlarını döndürmesi için hizmetinizi etki alanı-a üzerinde değiştirmeniz gerekir.

Bu biraz yardımcı olsa sevindim.


19
Ayrıca, çerezlerin belirli bir yola ayarlanabileceğini de belirtmek gerekir, bu nedenle çerez ayarlanmışsa path=/somethingve sayfayı talep ediyorsanız /another, çerez gönderilmez. Sayfayı talep ettiğinizde /somethingçerez beklendiği gibi gönderilir. Bu yüzden, çerezi ayarlayan kodu da kontrol edin.
styfle

2
jsonp isteği coockies gönderir mi?
albanx

1
@albanx Evet, bahsettiğim gereksinimler belirlenmişse. Diğerleri gibi normal bir istek ve çerez gönderir.
grip

1
@albanx bu diğer ilgili soru JSONP isteğinin özel çerezlerle nasıl yapılacağına dair bir örnek içerir
AntonioHerraizS

4
Wikipedia'da JSONP göre > bu yaklaşım CORS lehine terk edildi
Peter Dotchev

388

Alanlar arası senaryoda çalışıyorum. Oturum açma sırasında uzak sunucu Set-Cookie üstbilgisini Access-Control-Allow-Credentialstrue olarak ayarlanmış olarak döndürüyor .

Uzak sunucuya yapılan bir sonraki ajax çağrısı bu çerezi kullanmalıdır.

CORS'ler Access-Control-Allow-Credentialsetki alanları arası günlüğe kaydetmeye izin vermek için oradadır. Kontrol https://developer.mozilla.org/En/HTTP_access_control örnekler için.

Benim için JQuery'de bir hata gibi görünüyor (ya da en azından bir sonraki versiyonda olması gereken özellik).

GÜNCELLEME:

  1. Çerezler AJAX yanıtından otomatik olarak ayarlanmaz (alıntı: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/ )

    Neden?

  2. Çerezin değerini, manuel olarak ayarlamak için yanıttan alamazsınız ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader )

    Kafam karıştı..

    Parametre jquery.ajax()ayarlamayı istemenin bir yolu olmalıdır XMLHttpRequest.withCredentials = "true".

CEVAP: http://api.jquery.com/jQuery.ajax/xhrFields parametresini kullanmalısınız .

Belgelerdeki örnek şöyledir:

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

Sunucunun bu isteğe doğru yanıt vermesi de önemlidir. @ Frédéric ve @Pebbl'dan harika yorumlar kopyalanıyor:

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: *

Yani istek olduğunda:

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

Sunucu şu yanıtı vermelidir:

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

[payload]

Aksi takdirde, yük betiğe geri gönderilmez. Bkz. Https://developer.mozilla.org/tr-TR/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials


8
Harika ! Bu + 'yı Access-Control-Allow-Credentials üstbilgisini sunucu tarafında true olarak ayarlıyorum
Frédéric

ve bu Kimlik Bilgilerini nereden ayarlayabilirim?, Başlık Otorizasyonunda?, istek gövdesinde?
Francisco Corrales Morales

3
Cevabınız için teşekkürler :) sadece hızlı bir ekleme, 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

Bunların hiçbiri maalesef benim için işe yaramadı. Aynı isteği AngularJS'den çalıştırırsam çalışır, ancak jQuery'den, bu önerilerle bile oturum Çerezi geçilmez. (jQuery
v2.1.1

(OO) Beni çeşitli acılı saatlerden kurtardın. Ne mükemmel bir cevap! Teşekkürler! Bunları web sitemin genel kök .htaccess dosyasına eklemem gerekiyordu: <IfModule mod_headers.c> Üstbilgi kümesi Access-Control-Allow-Origin " localhost " Üstbilgi kümesi Access-Control-Allow-Credentials "true" </IfModule>
Vinay Vissh

48

kullanma

xhrFields: { withCredentials:true }

jQuery ajax çağrımın bir parçası olarak çözümün sadece bir parçasıydı. Ben de kaynaklardan SEÇENEKLER yanıtı döndürülen başlıkları gerekiyordu:

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

OPTIONS çağrısının yanıt başlığında "*" değil , yalnızca bir izin verilen "kaynak" ın olması önemlidir . Bunu isteğin kaynağını okuyarak ve yanıtı tekrar doldurarak başardım - muhtemelen kısıtlamanın orijinal nedenini atlattım, ancak benim kullanımımda güvenlik çok önemli değil.

W3C standardı boşlukla ayrılmış bir listeye izin verdiği için sadece tek bir köken gereksiniminden açıkça bahsetmeye değer olduğunu düşündüm - ama Chrome değil! http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB "uygulamada" biti.


41

Bunu init işlevinize koyun:

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

Çalışacak.


1
Günümü kurtardın! Kimlik düzeyinde yöntem düzeyinde benim için çalışmadı. Ama küresel olarak böyle sonunda işe yarıyor! Teşekkürler.
Paulius Matulionis

dikkatli olun, çünkü tüm isteklere çerez gönderir, diğer alanlar için eter (bunu beklemez ve Access-Control-Allow-Credentials gerektirerek başarısız olur)
gdbdable

12

Bu soruya zaten çok iyi yanıtlar var, ancak çerez alanıyla eşleştiği için oturum çerezinin gönderilmesini beklediğiniz durumu açıklığa kavuşturmanın yararlı olabileceğini düşündüm, ancak AJAX isteği olduğu için gönderilmiyor farklı bir alt alana yapılır. Bu durumda, ben atanmış bir çerez * .etkialanim.com etki ve bunu için bir AJAX isteği dahil edilecek isteyen ediyorum different.mydomain.com ". Varsayılan olarak, çerez gönderildiğinde almaz. Bu sorunu çözmek için oturum çerezinde HTTPONLY özelliğini devre dışı bırakmanız gerekmez.Yalnızca womblingin önerisini ( https://stackoverflow.com/a/23660618/545223 ) yapmanız ve aşağıdakileri yapmanız gerekir.

1) Ajax isteğinize aşağıdakileri ekleyin.

xhrFields: { withCredentials:true }

2) Farklı alt alanlardaki kaynaklar için yanıt başlıklarınıza aşağıdakileri ekleyin.

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

7

Diğer çözümleri denedikten ve hala işe yaramadıktan sonra, benim durumumda sorunun ne olduğunu öğrendim. ContentType'ı "application / json" yerine "text / plain" olarak değiştirdim.

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

4

Ben de aynı sorunu yaşıyordu ve bazı kontroller sadece benim scriptid sadece çerez almak değildi kontroller yapıyor.

Ben benim çerçeve (Django) varsayılan olarak HttpOnly ile sessionid çerez geçiyordu tarayıcıda sessionid çerez değerine bakarak anladım. Bu, komut dosyalarının oturum kimliği değerine erişimi olmadığı ve bu nedenle isteklerle birlikte geçirmediği anlamına geliyordu. Pek çok şey erişim kısıtlaması gerektiren Ajax kullandığında HttpOnly'nin varsayılan değer olacağı saçma.

Bunu düzeltmek için bir ayarı değiştirdim (SESSION_COOKIE_HTTPONLY = False), ancak diğer durumlarda çerez yolunda bir "HttpOnly" bayrağı olabilir


2
Bunu yapma. İstemci tarafı komut dosyasının, en yaygın XSS saldırı vektörü olan oturum çerezine erişmesine izin verir. Owasp.org/index.php/HttpOnly
Jason Elkin


0

Localhost ve dev ortamında PHPSESSID çerez sorununu ayarlama konusunda sadece 2 sentim. Ben locahost benim REST API uç noktasına AJAX çağrısı yapmak. Adresinin olduğunu söyleyin mysite.localhost/api/member/login/(geliştirici ortamımdaki virtal host).

  • Postacı'da bu isteği yaptığımda işler iyi gidiyor ve PHPSESSID yanıtla ayarlanıyor.

  • Bu son noktayı AJAX aracılığıyla Browsersync proxy sayfasından istediğimde (örneğin, 122.133.1.110:3000/test/api/login.phptarayıcı adres mysite.localhostsatırımdan etki alanının farklı olup olmadığına bakın) PHPSESSID çerezler arasında görünmüyor.

  • Bu isteği doğrudan aynı etki alanındaki sayfadan yaptığımda (yani mysite.localhost/test/api/login.php) PHPSESSID iyi ayarlanmış.

Yani bu, yukarıdaki @flu yanıtında belirtildiği gibi, bir menşe köken isteği çerezleri sorunu


0

Başka birine yardımcı olması durumunda senaryomu ve çözümümü ekleme. RESTful API'leri kullanırken benzer bir durumla karşılaştım. HTML / Script / CSS dosyalarını barındıran Web sunucum ve API'leri açığa çıkaran Uygulama Sunucusu aynı etki alanında barındırıldı. Ancak yol farklıydı.

web sunucusu - alan adım / web sayfaları /abc.html

Kullanılmış abc.js seti çerez adında MyCookie

uygulama sunucusu - alan adım / webapis / hizmetadı.

api çağrılarının yapıldığı

Mydomain / webapis / servicename içinde çerez bekliyordum ve okumaya çalıştım ama gönderilmiyordu. Cevabın yorumunu okuduktan sonra tarayıcının geliştirme aracında mycookie'nin yolunun "/ webpages " olarak ayarlandığını ve dolayısıyla

etkialanım / webapis / hizmet adı

Yani jquery'den çerez ayarlarken, bunu yaptım -

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

-5

Belki% 100 soruyu cevaplamak değil, ama ajax innovastudio editörünün assetmanager bir dosya yüklerken bir oturum sorunu çözme umuduyla tökezledi. Sonunda çözüm basitti: flash yükleyicileri var. Devre dışı bırakma (ayar

var flashUpload = false;   

varlık.php) ve ışıklar tekrar yanıp sönmeye başladı.

Bu sorunları ayıklamak çok zor olabileceğinden, yükleme işleyicisine aşağıdakine benzer bir şey koymanın sizi doğru yolda ayarlayacağını buldum:

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

Günlüğe bir dalış ve ben hiçbir çerez gönderildiği eksik oturumu hemen gördüm.


Yukarıdaki örnek işe yarayacağını sanmıyorum, çünkü oturum çerezi olmadığında, $ sn değeri ne olurdu? (rastgele bir veya belki de null), alternatif olarak kullanıcılar oturum_adı'nı bir GET değerinden session_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();bu şekilde ayarlayabilir , böylece bir şey elde ederlerdi
Steel Brain

Bu tam olarak nasıl sorunu buldum: bu flaş yükleyici thingy gönderirken oturum yok. GET değişken oturum tanımlayıcısını kullanmak kötü bir fikir olduğu ve çerez çalışmadığı için onu attım. Kimin umrunda, flaş zaten geçmişte kaldı.
Ellert van Koperen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.