jqueryの.ajax()メソッドがセッションCookieを送信しないのはなぜですか?


338

$.ajax()サイト経由でログインした後$.ajax()、そのサイトに2番目のリクエストを送信しようとしていますが、FireBugを使用して送信されたヘッダーを確認すると、リクエストにセッションCookieが含まれていません。

何が悪いのですか?


2
ajaxのCookieがWeb Cookieの後に来て、FireBugが最初のページのCookieをキャッチする場合があります。
Chris

1
意味がわかりませんでしたが、ブラウザのアドレスバーにリクエストURLを貼り付けてFirebugをもう一度確認すると、サーバーに送信されたヘッドレスのCookieを確認できます。解決策はありますか?
user345625

したがって、私はajaxもブラウザと同じように処理できると思います
user345625

使用しているコードは何ですか?
ディーンハーディング

ブラウザは、ajaxリクエスト、jquery、またはその他の間にサーバーによって設定されたCookieを作成します。ajaxリクエストへの応答を確認し、設定するサーバーからCookieが返されたことを確認しましたか?それもなど、Cookieを設定しないように、サーバーのコードに問題がある可能性があります
デヴィッド・

回答:


218

AJAX呼び出しは、呼び出しているURLが呼び出しスクリプトと同じドメインにある場合にのみCookieを送信します。

これは、クロスドメインの問題である可能性があります。

おそらくwww.domain-a.com、呼び出しスクリプトがオンのときにURLを呼び出そうとした可能性がありますwww.domain-b.com(つまり、クロスドメイン呼び出しを行った場合、ブラウザーはプライバシーを保護するためにCookieを送信しません)。

この場合、オプションは次のとおりです。

  • domain-bに存在し、リクエストをdomain-aに転送する小さなプロキシを作成します。ブラウザは、呼び出し元のスクリプトと同じサーバー上にあるため、プロキシを呼び出すことができます。
    次に、このプロキシは、domain-aに送信できるcookieの名前と値のパラメータを受け入れるように設定できます。ただし、これが機能するには、cookieの名前と、ドメインA上のサーバーが認証に必要な値を知る必要があります。
  • JSONオブジェクトをフェッチする場合は、代わりにJSONPリクエストを使用してください。jQueryはこれらをサポートします。ただし、有効なJSONP応答を返すように、domain-aでサービスを変更する必要があります。

それが少しでも役に立てば幸いです。


19
また、Cookieを特定のパスに設定できるため、Cookieが設定されていpath=/somethingてページをリクエストしている/another場合、Cookieは送信されません。ページをリクエストすると/something、Cookieは期待どおりに送信されます。したがって、Cookieを設定するコードも確認してください。
スタイフル2013

2
jsonpリクエストはcoockiesを送信しますか?
albanx 2014年

1
@albanxはい、私が言及した要件が設定されている場合。これは他の通常のリクエストであり、Cookieを送信します。
インフルエンザ

1
@albanxこの他の関連する質問には、カスタムCookieを使用してJSONPリクエストを実行する方法の例が含まれています
AntonioHerraizS 2014年

4
WikipediaのJSONPによると、このアプローチはCORSを支持して断念されました
Peter Dotchev

386

クロスドメインシナリオで運用しています。ログイン中に、リモートサーバーはAccess-Control-Allow-Credentials、trueに設定されたSet-Cookieヘッダーを返します。

リモートサーバーへの次のajax呼び出しでは、このCookieを使用する必要があります。

CORS Access-Control-Allow-Credentialsは、クロスドメインロギングを可能にするためのものです。例については、https://developer.mozilla.org/En/HTTP_access_controlを確認してください

私にとっては、JQueryのバグのようです(少なくとも次のバージョンでは機能予定)。

更新:

  1. CookieはAJAX応答から自動的に設定されません(引用:http : //aleembawany.com/2006/11/14/anatomy-of-a-well-designed-ajax-login-experience/

    どうして?

  2. 応答からCookieの値を取得して手動で設定することはできません(http://www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-getresponseheader

    よくわかりません..

    パラメータのjquery.ajax()設定を要求する方法が存在する必要がありXMLHttpRequest.withCredentials = "true"ます。

回答:http:xhrFields //api.jquery.com/jQuery.ajax/のパラメーター を使用する必要があります

ドキュメントの例は次のとおりです。

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

サーバーがこのリクエストに正しく応答することも重要です。@Frédéricおよび@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: *

したがって、リクエストが次の場合:

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

サーバーは次のように応答する必要があります:

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

[payload]

それ以外の場合、ペイロードはスクリプトに返されません。参照:https : //developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials


8
すごい !これを使用するために追加し、サーバー側でAccess-Control-Allow-Credentialsヘッダーをtrueに設定します
フレデリック

そして、それらの資格情報をどこに設定しますか?ヘッダーの自動化で?リクエストの本文で?
フランシスココラレスモラレス

3
答えてくれてありがとう:)ほんの少しの追加ですが、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

残念ながら、これはどれもうまくいきませんでした。AngularJSから同じリクエストを実行すると機能しますが、jQueryからは、これらの提案があってもセッションCookieは渡されません。(jQuery v2.1.1)
geoidesic

(OO)あなたは私をさまざまなつらい時間から救いました。完璧な答えです。ありがとう!これらを自分のウェブサイトのパブリックルート.htaccessに追加する必要がありました:<IfModule mod_headers.c>ヘッダーセットAccess-Control-Allow-Origin " localhost "ヘッダーセットAccess-Control-Allow-Credentials "true" </ IfModule>
Vinayヴィシュ

48

使用する

xhrFields: { withCredentials:true }

私のjQuery ajax呼び出しの一部として、ソリューションの一部にすぎませんでした。また、リソースからのOPTIONS応答でヘッダーを返す必要もありました。

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

OPTIONS呼び出しの応答ヘッダーには、「*」ではなく、許可された「origin」が1つだけあることが重要でした。これは、リクエストからオリジンを読み取り、それをレスポンスに追加することで実現しました。おそらく制限の元の理由を回避できますが、私のユースケースではセキュリティは最優先事項ではありません。

W3C標準ではスペースで区切られたリストが許可されているため、1つのオリジンのみの要件について明示的に言及する価値があると思いましたが、Chromeでは許可されていません。 http://www.w3.org/TR/cors/#access-control-allow-origin-response-header NB「実際」のビット。


41

これをあなたのinit関数に入れてください:

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

それが動作します。


1
あなたは私の日を救った!メソッドレベルでは、withCredentialsは機能しませんでした。しかし、このようにグローバルにやっとうまくいきました!ありがとう。
Paulius Matulionis 2015

すべてのリクエストにCookieを送信するので、注意してください。他のドメインの場合は、etherが必要です(これは
予期

12

この質問にはすでに多くの適切な回答がありますが、Cookieドメインが一致するためにセッションCookieが送信されると予想されるが、AJAXリクエストが送信されていないため送信されない場合を明確にすると役立つと思います別のサブドメインに作成されます。この場合、*。mydomain.comドメインに割り当てられたCookieがあり、それをdifferent.mydomain.comへのAJAXリクエストに含めたいと思っています。デフォルトでは、Cookieは送信されません。この問題を解決するために、セッションCookieでHTTPONLYを無効にする必要はありません。ウォンブルが提案すること(https://stackoverflow.com/a/23660618/545223)を実行し、以下を実行するだけです。

1)ajaxリクエストに以下を追加します。

xhrFields: { withCredentials:true }

2)異なるサブドメインのリソースの応答ヘッダーに以下を追加します。

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

7

他の解決策を試しても動作しない場合、私は自分の場合の問題を見つけました。contentTypeを「application / json」から「text / plain」に変更しました。

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

4

私はこれと同じ問題を抱えていて、いくつかのチェックを行ったところ、スクリプトは単にセッションID Cookieを取得していませんでした。

フレームワーク(Django)がデフォルトでHttpOnlyを使用してセッションID Cookieを渡していたことを、ブラウザーでセッションID Cookie値を調べてわかりました。これは、スクリプトがsessionid値にアクセスできなかったため、リクエストとともに渡されなかったことを意味します。多くのものがアクセス制限を必要とするAjaxを使用する場合、HttpOnlyがデフォルト値になるのはちょっとおかしいです。

これを修正するために設定(SESSION_COOKIE_HTTPONLY = False)を変更しましたが、それ以外の場合は、Cookieパスの「HttpOnly」フラグである可能性があります


2
こんなことしないで。クライアント側のスクリプトが、最も一般的なXSS攻撃ベクトルであるセッションCookieにアクセスできるようにします。owasp.org/index.php/HttpOnly
Jason Elkin

1

上記の回答で説明されている手順に加えて、localhostなどのlocalhostでポートを開発しlocalhost:8080ている場合は、Set-Cookieヘッダーでドメイン値を渡していないことを確認する必要もあります。Set-Cookieヘッダーで
ドメインをlocalhostに設定することはできません-これは誤りです-ドメインを省略するだけです。

参照してください。明示的なドメインとローカルホスト上のクッキーをし、なぜasp.netローカルホストにクッキーを作成していないのだろうか?


0

PHPSESSID Cookieの設定に関する私の2セントは、ローカルホスト上で、開発環境下にあります。locahostでREST APIエンドポイントにAJAX呼び出しを行います。そのアドレスがmysite.localhost/api/member/login/(私の開発環境の仮想ホスト)であるとします。

  • Postmanでこのリクエストを実行すると、問題が発生せず、PHPSESSIDに応答が設定されます。

  • BrowsersyncプロキシページからAJAXを介してこのエンドポイントを要求すると(たとえば122.133.1.110:3000/test/api/login.php、ブラウザーのアドレス行から、ドメインが異なることを確認してくださいmysite.localhost)、PHPSESSIDがCookieに表示されません。

  • 同じドメイン(つまりmysite.localhost/test/api/login.php)のページから直接このリクエストを行うと、PHPSESSIDは問題なく設定されます。

したがって、これは上記の @fluの回答で述べたように、クロスオリジンオリジンリクエストのCookieの問題です。


0

他の誰かを助ける場合に備えて、私のシナリオとソリューションを追加します。RESTful APIを使用しているときに同様のケースが発生しました。HTML /スクリプト/ CSSファイルをホストしているWebサーバーとAPIを公開しているアプリケーションサーバーは、同じドメインでホストされていました。ただし、パスは異なりました。

Webサーバ-はmydomain / ウェブページ /abc.html

中古abc.js名前付きセットクッキーmycookie

アプリサーバー-mydomain / webapis / servicename。

API呼び出しが行われた対象

mydomain / webapis / servicenameのCookieを予期していて、それを読み取ってみましたが、送信されませんでした。答えからのコメントを読んだ後、私はmycookieのパスが「/に設定されたことをブラウザの開発ツールで確認ウェブページへのサービスコールでは使用できませんので、」と

mydomain / webapis / servicename

だからjqueryからクッキーを設定しながら、これは私がやったことです-

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

-5

おそらく100%質問に答えているわけではありませんが、innovastudioエディタのassetmanagerからファイルアップロードをajax投稿するときに、セッションの問題を解決するためにこのスレッドに出くわしました。結局のところ、解決策はシンプルでした。フラッシュアップローダーを備えています。それを無効にする(設定

var flashUpload = false;   

asset.phpで)、ライトが再び点滅し始めました。

これらの問題はデバッグが非常に難しい場合があるため、次のようなものをアップロードハンドラーに入れると、あなた(この場合は私)が正しい方向に進むことがわかりました。

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

ログに飛び込んだところ、欠落しているセッションがすぐに見つかりました。Cookieが送信されていません。


上記の例ではうまくいかないと思います。セッションCookieがない場合、$ snの値はどうなるでしょうか。(ランダム1、または多分ヌル)、あるいはユーザーが例えばGET値からのセッション名を設定することができsession_name(isset($_GET['sess']) ? $_GET['sess'] : null);session_start();、このように、彼らが働く事取得したい
スチールブレイン

それがまさに私が問題を見つけた方法です:このフラッシュアップローダーのものから投稿するときにセッションがありません。GET変数のセッション識別子を使用することは悪い考えであり、Cookieが機能していなかったので、私はそれを捨てました。誰も気にせず、フラッシュはとにかく過去のものです。
Ellert van Koperen 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.