在写入响应流到线路时,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
集合的此行为?
答案 0 :(得分:5)
影响IIS 7的错误可能与受影响的IIS6不同。从4.7开始修复了这个bug,他提出的bug有以下ID:DevID 289778
。
以下是对它的描述: 在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添加到其中,并在{{1}上设置添加标记再次对象。这是错误。这会导致每次添加或删除任何其他cookie时,都会在每个响应cookie上设置Added标记。
这意味着如果您不修改或删除任何cookie,但添加至少一个,那么之前在其他管道阶段添加的所有cookie都将被复制。但是,如果您更改任何Cookie,或从HttpCookie
集合中删除任何Cookie,则会消除之前发生的所有重复项。
要解决此错误,只需添加和删除一些任意cookie,或在标题写出的同一事件中修改cookie。通常这是Response.Cookies
,除非您使用EndRequest
,Server.Transfer
,Server.Redirect
或Response.Flush
(除非您将Reponse.End
参数设置为在应用程序中的任何位置,在这种情况下,您必须在发生这些事件的同一事件中执行此操作。另外,不要忘记库中出现的任何问题或您使用的任何HttpModule。基本上,您只想将以下代码添加到每个事件中:
endReponse
答案 1 :(得分:0)
其他重复的Cookie错误描述:
上下文:Web窗体应用程序(使用窗体身份验证和URL重写)
问题:系统将会话cookie发送两次(除了在编译应用程序后收到的第一个请求之外)。
平台:IIS 10 / .NET Framework 4.7.2
Kevin解决方案确实可以解决该错误。
注意:
不需要随机的cookie名称。
在asp.net Web表单页面上,可以在Load事件上使用此替代方法。
答案 2 :(得分:-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");
}
答案 3 :(得分:-1)
如果您在更改cookie值而不返回客户端(server.Transfer)之后在页面之间导航,则会复制cookie。