Is IISExpress Single-Threaded?

2019-06-02 00:48发布

I am in the process of writing a custom .Net app that utilizes Claims for security, since we're crossing many boundaries - web, API, batch processing and so on. During development, there are occasions where I'll create something in the system while logged in via Chrome and then I'll go to test the newly created item via a different account in Edge and somehow HttpContext.Current.User.Identity corresponds to my Chrome session. I do set Thread.CurrentPrincipal behind the scenes, but my understanding has always been that all requests into IIS spawn a new thread, so I can't figure out why the Edge requests are being processed as if they are the Chrome requests.

Is it possible that it's sharing this information because Visual Studio is in debug mode?

1条回答
我想做一个坏孩纸
2楼-- · 2019-06-02 01:46

Yes, IIS (and thus IISExpress, which is IIS packaged in an "application" format) is multi-threaded. However, you have made some incorrect assumptions.

First, no. A new request does NOT spawn a new thread, it runs on a thread pool thread, and these thread pools are re-used after the previous request finishes (or, as you'll see in a minute, when an async request waits).

Second, you should NOT set Thread.CurrentPrincipal, because not only is IIS multi-threaded, it's asynchronous. This means that if your thread waits, when it resumes it might be running on a different thread than the thread it started on.

Third, Thread.CurrentPrincipal is typically the identity of the worker process (or AppPool) identity, changing this changes the security context the entire thread runs under. A much better option is to use the WindowsImpersonationContext class to do impersonation (which is what I assume you're trying to do).

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
}

If you do need to set a custom principal you should usually be using HttpContext.Current.User rather than Thread.CurrentPrincipal.

查看更多
登录 后发表回答