This post originated from an RSS feed registered with .NET Buzz
by Scott Hanselman.
Original Post: System.Threading.Thread.CurrentPrincipal vs. System.Web.HttpContext.Current.User or why...
Feed Title: Scott Hanselman's ComputerZen.com
Feed URL: http://radio-weblogs.com/0106747/rss.xml
Feed Description: Scott Hanselman's ComputerZen.com is a .NET/WebServices/XML Weblog. I offer details of obscurities (internals of ASP.NET, WebServices, XML, etc) and best practices from real world scenarios.
Warning: I find this fascinating and amazing as a caused a suble bug and was generally
bizarre today. You likely don't care. :)
I have some code in an ASP.NET custom FormsAuthentication Login that looks something
like this:
// This principal will flow throughout the request.
VoyagerPrincipal principal = new VoyagerPrincipal(yada, yada, yada);
// Attach the new principal object to the current HttpContext
object
HttpContext.Current.User = principal;
It it called on the Global.asax's AuthenticateRequest so everything is all setup before
the Page's events fire. It provides a custom IPrincipal that integrates our
eFinance Server with ASP.NET. It's quite a lovely subsystem, IMHO.
Other operations count on being able to get this 'Call Context' IPrincipal from the
current thread at any time. In another section of code someone was doing this
in the MIDDLE of the HttpRequest (somewhere in the Page_Load) after having JUST called
the routine above for the first time:
return Thread.CurrentPrincipal as VoyagerPrincipal;
Assuming, of course that the Thread's CurrentPrincipal is that same Principal.
And 99.999% percent of the time it is, except when it isn't at all.
In the instance where someone calls the first chunk of code then expects to be able
to call the second chunk within the same HttpRequest, the Thread.CurrentPrincipal
contains a GenericPrincipal populated much earlier by the HttpApplication.
(Or a WindowsPrincipal, depending on your settings).
When the first chunk of code runs in the Global.asax's AuthenticateRequest these two
properties ARE in fact the same object
When the first chunk of code runs in the context of a Page (read: later!) these properties
are NOT the same object.
Why? Reflector tells us in the HttpApplication's internal OnThreadEnter:
I had assumed, wrongly, that these two objects were coming from the same object reference
always. In fact, they are early on, but you can (as I did) change one without
changing the other. So, the first chunk of code becomes this:
// This principal will flow throughout the request.
VoyagerPrincipal principal = new VoyagerPrincipal(yada, yada, yada);
// Attach the new principal object to the current HttpContext
object
HttpContext.Current.User = principal;
// Make sure the Principal's are
in sync
System.Threading.Thread.CurrentPrincipal = System.Web.HttpContext.Current.User;
And all is right with my world, and the folks can continue to get the expected behavior
when doing a "mid-page" FormAuthentication login.