web-dev-qa-db-ja.com

AJAXリクエストが返された後、ブラウザがCookieを設定しないのはなぜですか?

$ .ajaxを使用してajaxリクエストを作成しています。応答にはSet-Cookieヘッダーセット(Chrome devツール)でこれを確認しました。しかし、ブラウザーはnot応答を受信した後にCookieを設定してください!ドメイン内の別のページに移動すると、Cookieは送信されません(注:クロスドメインAjaxリクエストを行っていません。リクエストはドキュメントと同じドメインにあります。 )

私は何が欠けていますか?

[〜#〜] edit [〜#〜]:私のajaxリクエストのコードは次のとおりです。

$.post('/user/login', JSON.stringify(data));

Chrome devツールで示されるように、リクエストは次のとおりです。

Request URL:https://192.168.1.154:3000/user/login
Request Method:POST
Status Code:200 OK

Request Headers:
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:35
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
DNT:1
Host:192.168.1.154:3000
Origin:https://192.168.1.154:3000
Referer:https://192.168.1.154:3000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36
X-Requested-With:XMLHttpRequest

Form Data:
{"UserId":"blah","Password":"blah"}:

応答:

Response Headers:
Content-Length:15
Content-Type:application/json; charset=UTF-8
Date:Sun, 16 Mar 2014 03:25:24 GMT
Set-Cookie:SessionId=MTM5NDk0MDMyNHxEdi1CQkFFQ180SUFBUkFCRUFBQVRfLUNBQUVHYzNSeWFXNW5EQXNBQ1ZObGMzTnBiMjVKWkFaemRISnBibWNNTGdBc1ZFcDNlU3RKVFdKSGIzQlNXRkkwVjJGNFJ6TlRVSHA0U0ZJd01XRktjMDF1Y1c1b2FGWXJORzV4V1QwPXwWf1tz-2Fy_Y4I6fypCzkMJyYxhgM3LjVHGAlKyrilRg==; HttpOnly
44
Matt Fichman

OK、だから私はついに問題を見つけました。 AJAXリクエストでCookieを送信する場合、Pathオプションの設定が重要であることがわかります。Path=/、例:

Set-Cookie:SessionId=foo; Path=/; HttpOnly

...別のページに移動すると、ブラウザがCookieを設定します。 Pathを設定しないと、ブラウザは「デフォルト」パスを使用します。どうやら、AJAXリクエストによって設定されるCookieのデフォルトパスは、ページに直接移動するときに使用されるデフォルトパスとは異なります。Go/ Martiniを使用しているので、私がこれを行う側:

session.Options(session.Options{HttpOnly: true, Path:"/"})

Python/Ruby /などと思います。 Pathを設定するための同様のメカニズムがあります。

参照: PHPおよびAJAX)のcookieの問題

52
Matt Fichman

新しいfetch AP​​Iを使用している場合は、credentialsを含めることができます。

fetch('/users', {
  credentials: 'same-Origin'
})

それは私のためにそれを修正したものです。

特に、ポリフィルの使用: https://github.com/github/fetch#sending-cookies

36
atomkirk

@atomkirkの answer はあまり当てはまりませんでした

  1. fetch AP​​Iを使用しません
  2. 私はクロスサイトリクエスト(つまりCORS)を作成していました

しかし、答えはこれらの飛躍を助けました:

fetch AP​​I CORSリクエスト Cookieの送信と受信の両方に_{credentials:'include'}_ が必要

CORSリクエストの場合、「include」値を使用して、 sending クレデンシャルを他のドメインに許可します。

_fetch('https://example.com:1234/users', {   
            credentials: 'include' 
})
_

...サーバーから accepting cookieをオプトインするには、資格情報オプションを使用する必要があります。


_{credentials:'include'}_は単に設定します _xhr.withCredentials=true_

fetchコードを確認

_if (request.credentials === 'include') {
      xhr.withCredentials = true
 } 
_

プレーンJavascript/XHR.withCredentials は重要な部分です。


jQueryを使用している場合、 withCredentialsを設定できます using $.ajaxSetup(...)

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

Angularを使用している場合、 _$http_ service config argwithCredentialsプロパティを受け入れます:

_$http({
    withCredentials: true
});
_

リクエストに関しては、_xhr.withCredentials=true_; Cookieヘッダーが送信されます

_xhr.withCredentials=true_を変更する前に

  1. レスポンスにSet-Cookieの名前と値が表示されましたが、開発者ツールのChromeの[アプリケーション]タブに名前と empty value が表示されました
  2. 後続のリクエストは送信しませんでしたCookieリクエストヘッダー。

変更後_xhr.withCredentials=true_

  1. 私は / Cookieの name およびCookieの value をChromeの[アプリケーション]タブに表示できました(Set-Cookieヘッダーと一致する値)。
  2. 後続のリクエスト did は同じ値を持つCookieリクエストヘッダーを送信するため、サーバーは「認証済み」として処理しました

応答に関して:サーバーは特定のAccess-Control- *ヘッダーを必要とする場合があります

たとえば、これらのヘッダーを返すようにサーバーを構成しました。

  • Access-Control-Allow-Credentials:true
  • Access-Control-Allow-Origin:https:// {your-Origin}:{your-port}

応答ヘッダーにこのサーバー側の変更を加えるまで、Chrome

_https://{saml-domain}/saml-authn_の読み込みに失敗しました:_https://{saml-domain}/saml-redirect_からのリダイレクトがCORSポリシーによってブロックされました:

応答の_'Access-Control-Allow-Credentials'_ヘッダーの値は_''_です。これは、要求の資格情報モードが_'true'_の場合は_'include'_でなければなりません。したがって、Origin _https://{your-domain}_はアクセスを許可されません。

XMLHttpRequestによって開始された要求の資格情報モードは、withCredentials属性によって制御されます。

このAccess- *ヘッダーを変更した後、Chromeはエラーをログに記録しませんでした。ブラウザーは、後続のすべての要求について認証済みの応答を確認しました。

16
The Red Pea

これは、誰かがこの質問にランダムに陥るのを助けるかもしれません。

サーバーが証明書を持っていなくても、http://ではなくhttps://でURLを強制すると、Chrome文句がこの問題を解決します。

1
CResults