System.Threading.Thread.CurrentPrincipal与System.Web.HttpContext.Current.User或为什么FormsAuthentication可...

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:

我在ASP.NET自定义FormsAuthentication登录中有一些代码,看起来像这样:

// This principal will flow throughout the request.
VoyagerPrincipal principal = new VoyagerPrincipal(yada, yada, yada);

//此委托人将遍历整个请求。 VoyagerPrincipal负责人=新的VoyagerPrincipal(yada,yada,yada);

// Attach the new principal object to the current HttpContext object
HttpContext.Current.User = principal;

//将新的主体对象附加到当前的HttpContext对象HttpContext.Current.User =主体;

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.

它调用了Global.asax的AuthenticateRequest,因此在触发页面事件之前都已完成所有设置。 它提供了一个自定义IPrincipal,将我们的eFinance Server与ASP.NET集成在一起。 恕我直言,这是一个非常可爱的子系统。

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:

其他操作依赖于能够随时从当前线程获取此“调用上下文” IPrincipal。 在另一部分代码中,有人在第一次调用上面的例程之后,就在HttpRequest的中间部分(在Page_Load中的某个地方)执行了此操作:

return Thread.CurrentPrincipal as VoyagerPrincipal;

返回Thread.CurrentPrincipal作为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.

假设,当然,线程的CurrentPrincipal是相同的Principal。 剩下的时间为99.999%,除非完全没有。

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

在有人呼叫代码的第一个块,然后希望能够调用在同一个HttpRequest的第二块的情况下,包含Thread.CurrentPrincipal中一个的GenericPrincipal由HttpApplication的要早得多填充。 (或WindowsPrincipal,取决于您的设置)。

  • When the first chunk of code runs in the Global.asax's AuthenticateRequest these two properties ARE in fact the same object

    当第一段代码在Global.asax的AuthenticateRequest中运行时,这两个属性实际上是同一对象
  • 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:

为什么? Reflector在HttpApplication的内部OnThreadEnter中告诉我们:

internal void OnThreadEnter()
{
      this._savedContext = HttpContextWrapper.SwitchContext(this._context);
      this._context.Impersonation.Start(false, true);
      HttpRuntime.RequestTimeoutManager.Add(this._context);this.SetPrincipalOnThread(this._context.User);      this.SetCulture(false);
}

内部无效的OnThreadEnter() { this._savedContext = HttpContextWrapper.SwitchContext(this._context); this._context.Impersonation.Start(false,true); HttpRuntime.RequestTimeoutManager.Add(this._context); this.SetPrincipalOnThread(this._context.User); this.SetCulture(false); }

internal void SetPrincipalOnThread(IPrincipal principal)
{
      if (!this._restorePrincipal)
      {
            this._restorePrincipal = true;
            this._savedPrincipal = Thread.CurrentPrincipal;
      }      Thread.CurrentPrincipal = principal;}

内部void SetPrincipalOnThread(IPrincipal主体) { 如果(!this._restorePrincipal) { this._restorePrincipal = true; this._savedPrincipal = Thread.CurrentPrincipal; }      Thread.CurrentPrincipal =主体; }

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);

//此委托人将遍历整个请求。 VoyagerPrincipal负责人=新的VoyagerPrincipal(yada,yada,yada);

// Attach the new principal object to the current HttpContext object
HttpContext.Current.User = principal;

//将新的主体对象附加到当前的HttpContext对象HttpContext.Current.User =主体;

// Make sure the Principal's are in sync
System.Threading.Thread.CurrentPrincipal = System.Web.HttpContext.Current.User;

//确保主体同步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.

我的世界一切正常,当进行“中间页” FormAuthentication登录时,人们可以继续获得预期的行为。

翻译自: https://www.hanselman.com/blog/systemthreadingthreadcurrentprincipal-vs-systemwebhttpcontextcurrentuser-or-why-formsauthentication-can-be-subtle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值