iis - ASP.NET Cookies BUG - multiple cookies duplicated randomly? -
it seems there annoying bug in asp.net cookie handling during writing of response-stream wire. set-cookie
headers multiplied randomly.
my example setup is: asp.net mvc4 on iis8 express server, same issue happens on iis7 integrated mode, , found posts same issue iis6 in 2009. seem issue exists while.
for example, in global.asax.cs subscribe beginrequest event , write httpresponse.cookie collection in event handler:
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")); } }
this will, already, output "onbeginrequest" set-cookie header twice. but, if similar done httpapplication events (authenticaterequest, acquirerequeststate, etc... total ~20 events), header of http response sent browser have lot of duplicates written. it's obvious after event writing of cookies start begging.
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
even worse, if same cookie written in 1 event handler, updated in another, duplicates different values appear in header.
are there settings or workaround can prevent behavior of default httpresponse.cookies
collection?
the bug impacting iis 7 not same bug impacted iis6. bug fixed of 4.5.2, , fixed of 4.5, don't have easy access copy of version. bug in question has fiollowing id: devid 251951
.
background
here description of it: in iis7, every time leave asp.net pipeline return iis pipeline, cookie headers added if needed. in integrated mode, leave asp.net pipeline between events.
so when writes out cookies needed, checks if cookies have been removed. if not checks if cookies have been added. if adds header cookie. checks if cookies have been modified. if adds header it. while iterates cookies, makes note of modified.
if cookies removed, or modified deletes set-cookie headers, , writes out new set. (or @ least tries. if headers have been flushed, not possible.)
so far good. upon rentering managed pipeline, read response headers in , reconstitute response cookies. needed since unmanaged module may have added new response cookies. although added cookies causes them marked added, code unsets added flag. so far still good, right?
the bug
well not exactly. every time cookie added (or removed from) response.cookies
collection, request.cookies
collection completely releoaded, , response cookies added it, setting add flag on httpcookie
object again. bug. causes added flag set on every response cookie every time other cookie added or removed.
this means last 1 cookie duplicated each time renter managed pipeline, , yet make no changes cookies. if add 1 cookie, cookies added duplicated. however, if change cookie, or remove cookie response.cookies
collection, eliminate duplicates occured.
the hackish workaround
to work around bug, add , remove arbitrary cookie, or modify cookie during same event headers written out. endrequest
, except if use server.transfer
, server.redirect
, response.flush
, or reponse.end
(unless set endreponse
parameter false) anywhere in app, in case must in same event occur. don't forget occurances of occur in libraries, or httpmodules use. basically, want add following code every single event:
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 headers written, //in case need not anything. }
Comments
Post a Comment