【问题标题】:Is IISExpress Single-Threaded?IISExpress 是单线程的吗?
【发布时间】:2017-04-13 02:56:10
【问题描述】:

我正在编写一个自定义 .Net 应用程序,该应用程序利用声明来保证安全性,因为我们跨越了许多边界 - Web、API、批处理等等。在开发过程中,有时我会在通过 Chrome 登录时在系统中创建一些东西,然后我会通过 Edge 中的另一个帐户去测试新创建的项目,不知何故 HttpContext.Current.User.Identity 对应于我的 Chrome 会话。我确实在幕后设置了Thread.CurrentPrincipal,但我的理解一直是所有进入 IIS 的请求都会产生一个新线程,所以我无法弄清楚为什么 Edge 请求会像 Chrome 请求一样被处理。

是否有可能因为 Visual Studio 处于调试模式而共享此信息?

【问题讨论】:

  • "...对 IIS 的请求会产生一个新线程..." - 很可能该请求将进入下一个可用线程池线程。因此,随着时间的推移,线程 ID 不会是唯一的
  • @rubyhaus 实际上你关心的是什么,我假设当 chrome 中有同一个用户的请求时,你不想在其他浏览器中允许他,这是你想要实现的吗?

标签: c# asp.net claims-based-identity httpcontext


【解决方案1】:

IIS(因此 IISExpress,它是以“应用程序”格式打包的 IIS)是多线程的。但是,您做出了一些错误的假设。

首先,不。新请求不会产生新线程,它在线程池线程上运行,并且在前一个请求完成后(或者,正如您稍后将看到的,当异步请求等待时),这些线程池会被重新使用。

其次,您不应该设置Thread.CurrentPrincipal,因为 IIS 不仅是多线程的,而且是异步的。这意味着如果您的线程等待,当它恢复时,它可能在与它启动的线程不同的线程上运行。

第三,Thread.CurrentPrincipal 通常是工作进程(或 AppPool)身份的身份,更改此身份会更改整个线程运行的安全上下文。更好的选择是使用 WindowsImpersonationContext 类进行模拟(我假设您正在尝试这样做)。

WindowsIdentity clientId = (WindowsIdentity)User.Identity;

// When 'using' block ends, the thread reverts back to previous Windows identity,
// because under the hood WindowsImpersonationContext.Undo() is called by Dispose()
using (WindowsImpersonationContext wic = clientId.Impersonate())
{
    // do your work that needs the identity
}

如果您确实需要设置自定义主体,您通常应该使用 HttpContext.Current.User 而不是 Thread.CurrentPrincipal。

【讨论】:

  • 我确实在web端设置了HttpContext.Current.User,但是没有到处引用System.Web,如何让底层库(主要是业务层)知道认证用户是谁?我试图避免引用 System.Web,因为并非所有东西都会使用 Web 组件。长期以来,我一直认为 Microsoft 的 Membership API 设置了 ThreadPrincipal,因此走这条路。
  • @RubyHaus - 是的,微软的代码经常做很多我们自己通常不应该做的事情,因为微软知道它在做什么并正确处理清理和边缘情况,我们通常不知道关于内部结构,通常最好避免它们。你在做某种自定义身份验证吗?您可以简单地将 Principal 从 Web 层传递给库吗?
  • 我希望有一个更无缝的方法来解决它,但我可能会想出一个方法来做到这一点。感谢您的帮助!
猜你喜欢
  • 2013-07-27
  • 2011-10-24
  • 2020-09-19
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-08
相关资源
最近更新 更多