it-swarm.com.de

Warum sendet die .ajax () -Methode von jquery kein Sitzungscookie?

Nachdem ich mich über $.ajax() an einer Site angemeldet habe, versuche ich, eine zweite $.ajax()-Anforderung an diese Site zu senden. Wenn ich jedoch die mit FireBug gesendeten Header überprüfe, wird in der Anfrage kein Sitzungscookie enthalten.

Was mache ich falsch?

309
user345625

AJAX-Aufrufe senden Cookies nur, wenn sich die von Ihnen aufgerufene URL in derselben Domäne befindet wie Ihr aufrufendes Skript.

Dies kann ein domänenübergreifendes Problem sein.

Möglicherweise haben Sie versucht, eine URL von www.domain-a.com aufzurufen, während Ihr aufrufendes Skript www.domain-b.com aktiviert war (mit anderen Worten: Sie haben einen domänenübergreifenden Anruf getätigt. In diesem Fall sendet der Browser keine Cookies zum Schutz Ihrer Privatsphäre).

In diesem Fall haben Sie folgende Möglichkeiten:

  • Schreiben Sie einen kleinen Proxy, der sich auf Domäne-b befindet und Ihre Anforderungen an Domäne-a weiterleitet. In Ihrem Browser können Sie den Proxy aufrufen, da er sich auf demselben Server befindet wie das aufrufende Skript.
    Dieser Proxy kann dann von Ihnen so konfiguriert werden, dass er einen Cookie-Namen und einen Werteparameter akzeptiert, die er an domain-a senden kann. Damit dies funktioniert, müssen Sie den Namen des Cookies kennen und den Wert Ihres Servers auf Domäne-A für die Authentifizierung angeben.
  • Wenn Sie JSON-Objekte abrufen, verwenden Sie stattdessen eine JSONP -Anforderung. jQuery unterstützt diese. Sie müssen jedoch Ihren Dienst auf Domäne-A ändern, damit gültige JSONP-Antworten zurückgegeben werden.

Ich bin froh, wenn das auch ein bisschen geholfen hat.

199
flu

Ich arbeite in einem domänenübergreifenden Szenario. Während der Anmeldung gibt der Remote-Server den Set-Cookie-Header zusammen mit Access-Control-Allow-Credentials auf true zurück.

Der nächste Ajax-Aufruf an einen Remote-Server sollte dieses Cookie verwenden.

Access-Control-Allow-Credentials von CORS ermöglicht die domänenübergreifende Protokollierung. Überprüfen Sie https://developer.mozilla.org/En/HTTP_access_control für Beispiele.

Für mich scheint es ein Fehler in JQuery (oder zumindest in der nächsten Version) zu sein.

AKTUALISIEREN:

  1. Cookies werden nicht automatisch aus der Antwort von AJAX gesetzt (Zitat: http://aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/ )

    Warum?

  2. Sie können den Wert des Cookies nicht aus der Antwort erhalten, um ihn manuell festzulegen ( http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader ).

    Ich bin verwirrt..

    Es sollte eine Möglichkeit vorhanden sein, jquery.ajax() zu bitten, den XMLHttpRequest.withCredentials = "true"-Parameter festzulegen.

ANSWER: Sie sollten xhrFields param von http://api.jquery.com/jQuery.ajax/ verwenden.

Das Beispiel in der Dokumentation lautet:

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

Es ist auch wichtig, dass der Server diese Anfrage richtig beantwortet. Kopieren Sie hier tolle Kommentare von @ Frédéric und @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: *

Also wenn die Anfrage ist:

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

Server sollte antworten mit:

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

[payload]

Andernfalls wird die Nutzlast nicht an das Skript zurückgegeben. Siehe: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials

355
Kangur

Verwenden

xhrFields: { withCredentials:true }

als Teil meines jQuery Ajax-Aufrufs war nur ein Teil der Lösung. Ich musste auch die Header aus meiner Ressource in der Antwort OPTIONS zurückgeben lassen:

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

Es war wichtig, dass nur ein zulässiger "Ursprung" im Antwortheader des OPTIONS-Aufrufs war und nicht "*". Ich habe dies erreicht, indem ich den Ursprung der Anforderung gelesen und in die Antwort zurückgefüllt habe - wahrscheinlich, um den ursprünglichen Grund für die Einschränkung zu umgehen, aber in meinem Anwendungsfall steht die Sicherheit nicht an erster Stelle.

Ich dachte, es lohnt sich, ausdrücklich die Anforderung für nur einen Origin zu erwähnen, da der W3C-Standard eine durch Leerzeichen getrennte Liste zulässt - aber Chrome nicht! http: // www. w3.org/TR/cors/#access-control-allow-Origin-response-header NB= das "in der Praxis" -Bit.

Fügen Sie dies in Ihre init-Funktion ein: 

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

Es wird klappen.

38
Alex Athlan

Es gibt bereits viele gute Antworten auf diese Frage, aber ich dachte, es könnte hilfreich sein, den Fall zu klären, in dem Sie erwarten würden, dass das Sitzungscookie gesendet wird, weil die Cookie-Domain übereinstimmt. Es wird jedoch nicht gesendet, weil AJAX Die Anfrage wird an eine andere Subdomain gestellt. In diesem Fall habe ich ein Cookie, das der Domäne * .mydomain.com zugewiesen ist, und ich möchte, dass es in eine AJAX Anforderung an different.mydomain.com aufgenommen wird ". Standardmäßig wird das Cookie nicht gesendet. Sie müssen HTTPONLY für das Sitzungscookie nicht deaktivieren, um dieses Problem zu beheben. Sie müssen nur das tun, was von Wombling empfohlen wird ( https://stackoverflow.com/a/23660618/545223 ) und führen Sie die folgenden Schritte aus.

1) Fügen Sie Ihrer Ajax-Anfrage Folgendes hinzu.

xhrFields: { withCredentials:true }

2) Fügen Sie den Antwortheadern für Ressourcen in den verschiedenen Subdomänen Folgendes hinzu.

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

Nachdem ich die anderen Lösungen ausprobiert hatte und es immer noch nicht funktionierte, fand ich heraus, was das Problem in meinem Fall war. Ich habe contentType von "application/json" in "text/plain" geändert.

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

Ich hatte das gleiche Problem, und bei einigen Überprüfungen bekam mein Skript einfach nicht das Sessionid-Cookie.

Ich habe herausgefunden, als ich den Sessionid-Cookie-Wert im Browser sah, dass mein Framework (Django) den Sessionid-Cookie mit HttpOnly als Standard übergeben hat. Dies hatte zur Folge, dass Skripts keinen Zugriff auf den Wert für sessionid hatten und daher nicht mit Anforderungen weitergeleitet wurden. Es ist lächerlich, dass HttpOnly der Standardwert ist, wenn so viele Dinge Ajax verwenden, für das eine Zugriffsbeschränkung erforderlich ist. 

Um dies zu beheben, habe ich eine Einstellung geändert (SESSION_COOKIE_HTTPONLY = False), aber in anderen Fällen kann es ein "HttpOnly" -Flag im Cookie-Pfad sein

3
wiwa

Wenn Sie an localhost oder einem Port auf localhost wie localhost:8080 entwickeln, müssen Sie zusätzlich zu den in den obigen Antworten beschriebenen Schritten sicherstellen, dass Sie im Set-Cookie-Header keinen Domänenwert übergeben.
Sie können die Domäne im Set-Cookie-Header nicht auf localhost setzen. Das ist falsch. Lassen Sie die Domäne einfach weg. 

Siehe Cookies auf localhost mit expliziter Domain und Warum erstellt asp.net keine Cookies in localhost?

0
jitin

Nur 2 Cent beim Setzen des PHPSESSID-Cookies, wenn auf localhost und in dev-Umgebungen. Ich mache den AJAX - Aufruf an meinen REST - API-Endpunkt auf dem Locahost. Angenommen, die Adresse lautet mysite.localhost/api/member/login/ (virtal Host in meiner Entwicklungsumgebung).

  • Wenn ich diese Anfrage auf Postman stelle, laufen die Dinge gut und PHPSESSID wird mit der Antwort gesetzt.

  • Wenn ich diesen Endpunkt über AJAX von der Browsersync-Proxy-Seite aus anfrage (z. B. von 122.133.1.110:3000/test/api/login.php in meiner Browser-Adresszeile, siehe Domäne unterscheidet sich von mysite.localhost), erscheint PHPSESSID nicht unter Cookies.

  • Wenn ich diese Anfrage direkt von der Seite in der gleichen Domäne (d. H. mysite.localhost/test/api/login.php) aus mache, wird PHPSESSID einfach eingestellt.

Es handelt sich also um ein Problem mit Herkunftsort-Herkunfts-Cookies, wie in @flu answer oben erwähnt.

0
bob-12345