微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASP.NET Cookies BUG – 多个cookie随机复制?

在向线路写入响应流期间,ASP.NET cookie处理中似乎存在令人讨厌的错误. Set-Cookie标头随机倍增.

我的示例设置是:IIS8 Express服务器上的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标头.但是,如果对所有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

更糟糕的是,如果在1个事件处理程序中写入相同的cookie,然后在另一个事件处理程序中更新,则会在标题显示具有不同值的重复项.

是否有任何设置或解决方法可以阻止认HttpResponse.Cookies集合的此行为?

解决方法

影响IIS 7的错误可能与受影响的IIS6不同.这个错误从4.5.2开始修复,可能从4.5开始修复,但我无法轻松访问该版本的副本.有问题的bug有fiollowing ID:DevID 251951.

背景

这是对它的描述:
在IIS7中,每次离开asp.net管道返回IIS管道时,如果需要,都会添加cookie头.在集成模式下,您可以在大多数事件之间保留asp.net管道.

因此,当它根据需要写出cookie时,它会检查是否已删除任何cookie.如果没有,它会检查是否添加了任何cookie.如果是这样,它会为该cookie添加标题.它还会检查是否有任何cookie被修改.如果是这样,它会为它添加标题.虽然它迭代了cookie,但它会记录任何被修改内容.

如果删除了任何cookie,或者任何cookie被修改,那么它将删除所有Set-Cookie标头,并写出一个新的集合. (或者至少它会尝试.如果标题已被刷新,那么显然这是不可能的.)

到现在为止还挺好.但是,在重新编译托管管道时,我们会读回任何响应头并重新构建响应cookie.这是必需的,因为一些非托管模块可能添加了新的响应cookie.但是虽然添加了cookie会导致它们被标记为已添加,但代码会立即取消添加标记.所以到目前为止一切都还不错,对吗?

错误

好吧不完全是.每次向Response.Cookies集合添加cookie(或从中删除)时,Request.Cookies集合都完全被重新加载,然后将响应cookie添加到其中,再次在HttpCookie对象上设置add标志.这是错误.这会导致每次添加删除任何其他cookie时,都会在每个响应cookie上设置Added标记.

这意味着每次租用托管管道时,除了最后一个cookie之外的所有cookie都会被复制,但不会对cookie进行任何更改.如果您添加一个cookie,那么之前添加的所有cookie都将被复制.但是,如果您更改任何cookie,或从Response.Cookies集合中删除任何cookie,那么您将消除以前发生的所有重复项.

Hackish Workaround

解决错误,只需添加删除一些任意cookie,或在标题写出的同一事件中修改cookie.通常这将是EndRequest,除非你在应用程序的任何地方使用Server.Transfer,Server.Redirect,Response.Flush或Reponse.End(除非你将endReponse参数设置为false),在这种情况下你必须在发生这种情况的同一事件.另外,请不要忘记库中出现的任何问题或您使用的任何HttpModule.基本上,您只想将以下代码添加到每个事件:

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.
}

原文地址:https://www.jb51.cc/aspnet/247264.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐