11

ワイヤーへの応答ストリームの書き込み中に、ASP.NET cookie の処理に迷惑なバグがあるようです。Set-Cookieヘッダーはランダムに乗算されます。

私のセットアップ例は次のとおりです。IIS8エクスプレスサーバー上のASP.NET MVC4ですが、 IIS7統合モードでも同じ問題が発生し、2009年に同じ問題IIS6に関する投稿を見つけました。問題はしばらく存在するようです.

たとえば、Global.asax.cs では、BeginRequest イベントをサブスクライブし、イベント ハンドラーで HttpResponse.Cookie コレクションに書き込みます。

public class MvcApplication : System.Web.HttpApplication
{
    public override void Init()
    {
        base.Init();
        BeginRequest += OnBeginRequest;
    }

    void OnBeginRequest(object sender, EventArgs e)
    {
        Response.Cookies.Set(new HttpCookie("OnBeginRequest", "0"));
    }
}

これにより、既に "OnBeginRequest" Set-Cookie ヘッダーが 2 回出力されます。ただし、すべての HttpApplication イベント (AuthenticateRequest、AcquireRequestState など...合計 20 個のイベント) に対して同様の処理を行うと、ブラウザーに送信される HTTP 応答のヘッダーに大量の重複が書き込まれます。また、Cookie の書き込みが物乞いから開始されるイベントの後であることも明らかです。

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnResolveRequestCache=5; path=/
Set-Cookie: OnPostResolveRequestCache=6; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnResolveRequestCache=5; path=/
Set-Cookie: OnPostResolveRequestCache=6; path=/
Set-Cookie: OnMapRequestHandler=7; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnResolveRequestCache=5; path=/
Set-Cookie: OnPostResolveRequestCache=6; path=/
Set-Cookie: OnMapRequestHandler=7; path=/
Set-Cookie: OnPostMapRequestHandler=8; path=/
Set-Cookie: OnAcquireRequestState=9; path=/
Set-Cookie: OnPostAcquireRequestState=10; path=/
Set-Cookie: OnPreRequestHandlerExecute=11; path=/
X-AspNetMvc-Version: 4.0
X-AspNet-Version: 4.0.30319
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnResolveRequestCache=5; path=/
Set-Cookie: OnPostResolveRequestCache=6; path=/
Set-Cookie: OnMapRequestHandler=7; path=/
Set-Cookie: OnPostMapRequestHandler=8; path=/
Set-Cookie: OnAcquireRequestState=9; path=/
Set-Cookie: OnPostAcquireRequestState=10; path=/
Set-Cookie: OnPreRequestHandlerExecute=11; path=/
Set-Cookie: OnPostRequestHandlerExecute=12; path=/
Set-Cookie: OnReleaseRequestState=13; path=/
Set-Cookie: OnPostReleaseRequestState=14; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnResolveRequestCache=5; path=/
Set-Cookie: OnPostResolveRequestCache=6; path=/
Set-Cookie: OnMapRequestHandler=7; path=/
Set-Cookie: OnPostMapRequestHandler=8; path=/
Set-Cookie: OnAcquireRequestState=9; path=/
Set-Cookie: OnPostAcquireRequestState=10; path=/
Set-Cookie: OnPreRequestHandlerExecute=11; path=/
Set-Cookie: OnPostRequestHandlerExecute=12; path=/
Set-Cookie: OnReleaseRequestState=13; path=/
Set-Cookie: OnPostReleaseRequestState=14; path=/
Set-Cookie: OnUpdateRequestCache=15; path=/
Set-Cookie: OnPostUpdateRequestCache=16; path=/
Set-Cookie: OnLogRequest=17; path=/
Set-Cookie: OnPostLogRequest=18; path=/
Set-Cookie: OnEndRequest=19; path=/
Set-Cookie: OnBeginRequest=0; path=/
Set-Cookie: OnAuthenticateRequest=1; path=/
Set-Cookie: OnPostAuthenticateRequest=2; path=/
Set-Cookie: OnAuthorizeRequest=3; path=/
Set-Cookie: OnPostAuthorizeRequest=4; path=/
Set-Cookie: OnResolveRequestCache=5; path=/
Set-Cookie: OnPostResolveRequestCache=6; path=/
Set-Cookie: OnMapRequestHandler=7; path=/
Set-Cookie: OnPostMapRequestHandler=8; path=/
Set-Cookie: OnAcquireRequestState=9; path=/
Set-Cookie: OnPostAcquireRequestState=10; path=/
Set-Cookie: OnPreRequestHandlerExecute=11; path=/
Set-Cookie: OnPostRequestHandlerExecute=12; path=/
Set-Cookie: OnReleaseRequestState=13; path=/
Set-Cookie: OnPostReleaseRequestState=14; path=/
Set-Cookie: OnUpdateRequestCache=15; path=/
Set-Cookie: OnPostUpdateRequestCache=16; path=/
Set-Cookie: OnLogRequest=17; path=/
Set-Cookie: OnPostLogRequest=18; path=/
Set-Cookie: OnEndRequest=19; path=/
Set-Cookie: OnPreSendRequestContent=20; path=/
Set-Cookie: OnPreSendRequestHeaders=21; path=/
X-Powered-By: ASP.NET
Date: Mon, 20 May 2013 10:47:20 GMT
Content-Length: 4002

さらに悪いことに、同じ Cookie が 1 つのイベント ハンドラーに書き込まれ、別のイベント ハンドラーで更新された場合、異なる値を持つ重複がヘッダーに表示されます。

HttpResponse.Cookiesデフォルトコレクションのこの動作を防止できる設定または回避策はありますか?

4

4 に答える 4

6

IIS 7 に影響を与えるバグは、おそらく IIS6 に影響を与えるバグと同じではありません。このバグは 4.7 で修正されました。問題のバグの ID は次のとおりですDevID 289778

バックグラウンド

IIS7 では、asp.net パイプラインを離れて IIS パイプラインに戻るたびに、必要に応じて Cookie ヘッダーが追加されます。統合モードでは、ほとんどのイベント間で asp.net パイプラインを離れます。

そのため、必要に応じて Cookie を書き出すときに、削除された Cookie があるかどうかを確認します。そうでない場合は、Cookie が追加されているかどうかを確認します。その場合、その Cookie のヘッダーを追加します。また、Cookie が変更されているかどうかも確認します。その場合、ヘッダーを追加します。Cookie を繰り返し処理している間、変更されたものを記録します。

Cookie が削除された場合、または変更された場合、すべての Set-Cookie ヘッダーが削除され、新しいセットが書き込まれます。(または、少なくとも試行します。ヘッダーがフラッシュされている場合、明らかにこれは不可能です。)

ここまでは順調ですね。ただし、管理されたパイプラインに再び入ると、応答ヘッダーが読み込まれ、応答 Cookie が再構成されます。一部のアンマネージ モジュールが新しい応答 Cookie を追加した可能性があるため、これが必要です。その際、応答ヘッダーからコピーされた Cookie に対して追加フラグを設定しません。これまでのところ、すべてが順調ですよね?

不具合

正確ではありません。コレクションに Cookie が追加 (またはコレクションから削除) されるたびResponse.Cookiesに、Request.Cookiesコレクションが完全に再読み込みされ、応答 Cookie がコレクションに追加され、HttpCookieオブジェクトに追加フラグが再度設定されます。これがバグです。これにより、他の Cookie が追加または削除されるたびに、すべての応答 Cookie に Added フラグが設定されます。

これは、Cookie を変更または削除せずに少なくとも 1 つ追加すると、他のパイプライン ステージで以前に追加されたすべての Cookie が複製されることを意味します。ただし、Cookie を変更したり、コレクションから Cookie を削除したりするResponse.Cookiesと、以前に発生したすべての重複が削除されます。

ハック的な回避策

このバグを回避するには、任意の Cookie を追加および削除するか、ヘッダーが書き出されるのと同じイベント中に Cookie を変更します。アプリ内の任意の場所で、、、または(パラメーターを false に設定しない限り)EndRequestを使用する場合を除いて、通常は になります。その場合は、それらが発生するのと同じイベントでこれを行う必要があります。また、ライブラリや使用する HttpModule で発生するものについても忘れないでください。基本的に、次のコードをすべてのイベントに追加するだけです。Server.TransferServer.RedirectResponse.FlushReponse.EndendReponse

try{
   var guid=Guid.NewGuid();
   context.Response.Cookies.Add(new HttpCookie(guid.ToString(),string.Empty);
   context.Response.Cookies.Remove(guid.ToString());
}
catch(HttpException)
{
   //This means the headers were already written,
   //in which case we need not do anything.
}
于 2015-02-10T20:21:05.350 に答える
-1

Cookie の値を変更した後、クライアント (server.Transfer) に戻らずにページ間を移動すると、Cookie が複製されます。

于 2014-02-12T13:48:38.833 に答える
-1

cookie に値を設定するときは、最初にクリアします。.Clear()

var cookie = this.Request.Cookies.Get("MyCookie");
if (cookie == null)
{
   cookie = new HttpCookie("MyCookie");
   this.Response.Cookies.Add(cookie);
}
else
{
   cookie.Values.Clear();                       //crear firstly..
   cookie.Values.Add("AnyKey", "AnyValue");
}
于 2013-07-26T05:20:30.100 に答える