web-dev-qa-db-ja.com

ドメインが指定されているCookieと指定されていないCookie(ブラウザの不整合)

Cookieに関してブラウザ間で実際に矛盾があることに気付きました。

これはかなり長くなるので、ご容赦ください。

注:「testdomain.com」というホストファイルにドメインを設定しました。これはbug「localhost」を使用するとWONTが機能します。

注2:Cookieのコレクションを返す場合、名前でCookieを取得すると、Apache/PHPでこれがどのように機能するかを知りたいです。

ウィキペディア

ウィキペディアは次のように述べています: http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Path

ドメインとパス
Cookieドメインとパスは、Cookieの範囲を定義します。Cookieは、指定されたドメインとパスのサーバーにのみCookieを送り返すようブラウザに指示します。 指定しない場合、デフォルトでは、要求されたオブジェクトのドメインとパスになります。

プッシュダウンした場合:

Response.Cookies.Add(new HttpCookie("Banana", "2")
{

});

要求されたオブジェクトから、使用されているドメインがドメインであるCookieを取得する必要があります。この場合、「testdomain.com」である必要があります。

W3

W3はCookieの仕様で次のように述べています: http://www.w3.org/Protocols/rfc2109/rfc2109

ドメイン=ドメイン

オプション。 Domain属性は、Cookieが有効なドメインを指定します。 明示的に指定されたドメインは、常にドットで始まる必要があります。

プッシュダウンした場合:

Response.Cookies.Add(new HttpCookie("Banana", "1")
{
    Domain = Request.Url.Host
});

Host-nameを明示的にプッシュダウンし、Cookieに設定されたドメイン名を取得する必要があります。これには、ドットがプレフィックスとして付けられます。この場合は「.testdomain.com」です。

また、ウィキペディアに何があるかを示しています。

ドメインのデフォルトはrequest-Hostです。 (request-Hostの先頭にはドットがないことに注意してください。)


これまでのところ?

ドメインを定義する最初の方法を使用する場合:

Response.Cookies.Add(new HttpCookie("Banana", "1")
{
    Domain = Request.Url.Host
});

これが結果です:

IE9:1クッキー

IE with 1 cookie and domain explicitly set

Opera:1クッキー

Opera with 1 cookie and domain explicitly set

Firefox:1クッキー

Firefox with 1 cookie and domain explicitly set

Chrome:Cookie 1個

Chrome with 1 cookie and domain explicitly set

ご覧のとおり、OperaとIEは両方とも、ドットプレフィックスなしでEXPLICITドメインを設定します。

FirefoxとChrome DOは、EXPLICITドメインにドットプレフィックスを設定します。

次のコードを使用する場合:

Response.Cookies.Add(new HttpCookie("Banana", "2")
{

});

IE/Opera:どちらもまったく同じ結果、ドメインはドットプレフィックスなしです。

面白いことに、FirefoxとChromeはどちらもドットプレフィックスなしでCookieを作成します。

(すべてのCookieをクリアし、コードを再度実行しました)

Firefox:

Firefox with 1 cookie and domain explicitly set

クロム:

Chrome with 1 cookie and domain explicitly set

興味深いビット

ここが面白いところです。クッキーを次のように次々と書くと:

Response.Cookies.Add(new HttpCookie("Banana", "1")
{
    Domain = Request.Url.Host
});
Response.Cookies.Add(new HttpCookie("Banana", "2")
{

});

クッキー名に基づいていると想定しているため、個人的には、ブラウザに1つのCookieが存在することを期待します。

私が観察したことは次のとおりです。

IE/Operaでは、最後のCookieセットは使用されるCookieです。これは、Cookie名とドメイン名が同一であるためです。

ドットを使用してドメイン名を明示的に定義した場合、両方のブラウザーで同じ名前の最後のCookieである1つのCookieが引き続き表示されます。

一方、ChromeとFirefoxでは、複数のCookieが表示されます。

値をページにダンプするために、次のJavaScriptを作成しました。

<script type="text/javascript">

(function () {
    var cookies = document.cookie.split(';');
    var output = "";

    for (var i = 0; i < cookies.length; i++) {
        output += "<li>Name " + cookies[i].split('=')[0];
        output += " - Value " + cookies[i].split('=')[1] + "</li>";
    }

    document.write("<ul>" + output + "</ul>");
})();

</script>

結果は次のとおりです。

IE-2つのCookieセット(ブラウザは1を見る):

IE - 2 cookies set, the outcome

Opera-2つのCookieセット(ブラウザは1を見る):

enter image description here

Firefox-2つのCookieが設定され、ブラウザは2を表示します!:

enter image description here

Chrome-2つのCookieが設定され、ブラウザーは2を表示します!:

enter image description here


今、あなたはおそらくこれがすべてwtfだと思っています。

まあ:

  1. C#で名前でCookieにアクセスすると、1つのCookieが提供されます。 (その名前を持つ最初のCookie)
  2. ブラウザはすべてのCookieをサーバーに送信します
  3. ブラウザは、Cookieのキー/値以外の情報を送信しません。 (これは、サーバーがドメインを気にしないことを意味します)
  4. インデックスで取得すると、同じ名前の両方のCookieにアクセスできます

問題...

Cookieをプッシュダウンするときに、Cookieのドメインを指定するように認証を変更する必要がありました。

これはChromeとFirefoxで、サーバーは古い認証Cookieを認証しようとするため、ユーザーはログインできなくなりました。これは、(理解から)認証Cookie名を使用して取得するためですクッキー。

Cookieが2つある場合でも、最初のCookieが取得されますが、これは古いもので、認証に失敗し、ユーザーがログインしていません。時々、正しいCookieがリストの最初にあり、認証が成功します。

最初に、古いドメインのCookieをプッシュして期限切れにすることで、これを解決しました。これは、ChromeおよびFirefoxで機能しました。

しかし、両方のブラウザーがドメインを気にせず、名前に基づいてCookieのみを比較するため、IE/Operaが破損しました。

私の結論は、クッキーのドメインは完全に時間の無駄だということです。

ドメインを指定する必要があり、ユーザーがブラウザーのキャッシュをクリアすることを信頼できないと仮定します。この問題をどのように解決できますか?

更新:

.NETがユーザーをサインアウトする方法を掘り下げます。

if (FormsAuthentication._CookieDomain != null)
{
    httpCookie.Domain = FormsAuthentication._CookieDomain;
}

フォーム認証が期限切れの認証Cookieをプッシュすることは完全に可能であるように見えます。これは、ユーザーが認証されるCookieとはまったく関係ありません。現在の認証Cookieのドメインは使用しません。

ドメインはCookieを使用してサーバーにプッシュバックされないため、とにかく使用できません。

更新2

FormsAuthenticationが本当に壊れているようです。ユーザーを認証するときにCookieで明示的なドメイン名を使用し、セッションがタイムアウトするのを待ってからページを更新すると、FormsAuthenticationで使用されるCookieの生成方法により、ドメインがnullになり、ブラウザがドットレスドメイン。

Cookieに割り当てるには、フォームにドメインを事前に割り当てる必要があります。これにより、マルチテナントシステムが破損します...

44
Phill

@WilliamBZAの提案は最初の問題の解決に役立ちましたが、Cookieが暗黙的なドメインCookieを作成するというサインアウト/セッションタイムアウトのバグにより、ソリューションは...

。NETで明示的なCookieを使用しない... ever

あまりにも多くの問題があります。Form/ Domain、Cookie/Domainなどで明示的にすることで解決できます。正しいドメインがどこでも使用されるようにします。しかし、アプリケーションが複数のドメインをホストしている場合、またはマルチテナントである場合は、問題が大きくなりすぎます。

レッスンが学習されます。明示的なCookieを使用しないでください。

9
Phill

whyで助けられませんが、Cookieのドメインを使用するのではなく、サブアプリケーションごとに異なるCookie名を使用することで簡単に修正できます。

フォーム認証の場合、ASPXAUTH Cookieの名前を変更します。

5
WilliamBZA