WindowsIdentity.Impersonate()混淆 [英] WindowsIdentity.Impersonate() confusion

查看:79
本文介绍了WindowsIdentity.Impersonate()混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由IIS托管的Web应用程序.它配置有表单身份验证和匿名身份验证,并且启用了模拟. 应用程序池帐户是网络服务.匿名帐户是Costa. Costa可以访问数据库. NetworkService无法访问数据库.

I have a web application hosted by IIS. it is configured with Form Authentication and Anonymous authentication, and Impersonation is enabled. App Pool account is Network Service. Anonymous account is Costa. Costa is having access to database. NetworkService cannot access database.

问题在于请求线程(父线程)可以访问数据库,而子线程不能.

The problem is that Request thread (parent thread) can access the database but sub thread cannot.

要解决此问题.我将主线程的Windows标识对象发送到子线程,然后调用Impersonate().模拟是指使用模拟帐户分配当前线程Windows身份. 我的问题:这是一种好习惯吗?有风险吗?

To fix this. I send windows identity object of main thread to sub thread, then I call Impersonate(). Impersonate means "assign current thread Windows Identity with impersonated account. My question: Is that a good practice? Is there a risk?

\\Request thread code (Parent thread)

\\WindowsIdentity.GetCurrent() return Costa identity (impersonated)
requestFields.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
ThreadPool.QueueUserWorkItem(LogRequest, requestFields);

-

\\ Sub thread code that works
RequestFields requestFields = (RequestFields)obj;
HttpRequest httpRequest = requestFields.Request;

var impersonationContext = ((WindowsIdentity)requestFields.CurrentPrincipal.Identity).Impersonate();
.
.
.
impersonationContext.Undo();

推荐答案

工作线程没有自动从请求线程中冒充用户的原因是.NET线程池管理其创建和重用.线程.如果您是通过下面的示例代码自己创建线程的,那么我希望它会自动继承安全上下文(包括模拟),但是您也不会重用线程,这会增加执行成本(请参阅

The reason that the worker thread isn't automatically impersonating the user from the request thread is that the .NET thread pool manages the creation and re-use of its threads. If you created the thread yourself via the example code below, I would expect it to inherit security context (including impersonation) automatically, but you also wouldn't be re-using threads which would add some execution cost (see Thread vs ThreadPool for details on the differences between the two and the benefits of using a thread pool thread).

因为您知道IIS确实模仿了用户,并且根据

Since as you know IIS does impersonate users and according to http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx it uses the thread pool to process its requests, I would conclude that it is not dangerous to do impersonation on thread pool threads as long as you take steps to be as sure as possible that the impersonation will be undone even in exceptional circumstances. If the impersonation is not undone, you run the risk of other code that uses the thread pool (yours, other libraries, or the .NET framework itself) being assigned to a thread that is using some random identity instead of the application pool identity.

我不确定RequestFields类是什么(快速搜索似乎表明它不属于.NET框架),所以我不明白为什么有必要将WindowsIdentity包装在WindowsPrincipal中,因为您不要使用Identity以外的任何属性,它会迫使您强制转换到另一个线程上.如果您拥有这个类并且可以更改它,我建议您将CurrentPrincipal属性更改为直接采用WindowsIdentity,以便可以在不需要不必要的WindowsPrincipal包装器的情况下进行传递.

I'm not sure what the RequestFields class is (a quick search seems to indicate that it's not part of the .NET framework), so I don't understand why it is necessary to wrap the WindowsIdentity in a WindowsPrincipal since you don't use any properties other than Identity and it forces you to cast on the other thread. If you own this class and can change it, I'd recommend changing the CurrentPrincipal property to take the WindowsIdentity directly so it can be passed without the unnecessary WindowsPrincipal wrapper.

我认为您可以将当前的WindowsIdentity传递给另一个线程池线程,并以执行方式调用模拟.但是,您绝对应该将impersonationContext包装在using块中,或者将Undo包装在try/finally块的最后一部分中,该块从对Impersonate的调用开始,以确保即使在发生异常或线程中断的情况下也可以撤消模拟.您还应该确保还处置由WindowsIdentity.GetCurrent()创建的WindowsIdentity的副本,以便确定性地关闭对身份背后非托管用户令牌的所有引用(即,不通过垃圾回收器完成).

I think it's fine for you to pass the current WindowsIdentity to another thread pool thread and call Impersonate the way you're doing it. However, you should definitely either wrap impersonationContext in a using block or wrap the Undo in the finally part of a try/finally block that starts at the call to Impersonate to ensure that the impersonation is undone even in the event of an exception or thread abort. You should also make sure that the copy of the WindowsIdentity created by WindowsIdentity.GetCurrent() is disposed as well so all references to the unmanaged user token behind the identity are closed deterministically (i.e. not by garbage collector finalization).

用于创建新线程的示例代码:

Example code for creating a new thread:

Thread myThread = new Thread(LogRequest);

// the CLR will not wait for this thread to complete if all foreground threads
// have been terminated; this mimics the thread pool since all thread pool threads
//are designated as background threads
myThread.IsBackground = true;

myThread.Start(requestFields);

使用using块正确处理WindowsImpersonationContext和WindowsIdentity对象的示例代码(impersonationContext.Dispose将调用Undo):

Example code for properly disposing of the WindowsImpersonationContext and WindowsIdentity objects with a using block (impersonationContext.Dispose will call Undo):

using (var identity = (WindowsIdentity)requestFields.CurrentPrincipal.Identity)
using (var impersonationContext = identity.Impersonate())
{
    .
    .
    .
}

这篇关于WindowsIdentity.Impersonate()混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆