gpt4 book ai didi

c# - WindowsIdentity.Impersonate() 混淆

转载 作者:太空宇宙 更新时间:2023-11-03 13:13:57 25 4
gpt4 key购买 nike

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

问题是请求线程(父线程)可以访问数据库,但是子线程不能。

解决这个问题。我将主线程的 Windows 标识对象发送到子线程,然后调用 Impersonate()。模拟意味着“使用模拟帐户分配当前线程 Windows 标识。我的问题:这是一个好习惯吗?有风险吗?

\\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 线程池管理其线程的创建和重用。如果您通过下面的示例代码自己创建线程,我希望它自动继承安全上下文(包括模拟),但您也不会重新使用会增加一些执行成本的线程(有关详细信息,请参见 Thread vs ThreadPool关于两者之间的区别以及使用线程池线程的好处)。

如您所知,IIS 会模拟用户并且根据 http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx它使用线程池来处理它的请求,我认为在线程池线程上进行模拟并不危险,只要您采取措施尽可能确保即使在特殊情况下也能撤消模拟。如果未取消模拟,您将面临使用线程池(您的、其他库或 .NET 框架本身)的其他代码被分配给使用某种随机标识而不是应用程序池标识的线程的风险。

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

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

创建新线程的示例代码:

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 block 正确处理 WindowsImpersonationContext 和 WindowsIdentity 对象的示例代码(impersonationContext.Dispose 将调用撤消):

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

关于c# - WindowsIdentity.Impersonate() 混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27295991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com