Parallel.ForEach()更改模拟环境 [英] Parallel.ForEach() changes Impersonation Context

查看:179
本文介绍了Parallel.ForEach()更改模拟环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我们部署我们新创建ASP.NET应用程序到服务器,并很快我们意识到,有哪些是导致应用程序崩溃,一个陌生的与安全相关的问题。这是一个内部应用程序,我们使用模拟来管理用户访问的资源。但是,应用程序抛出一个拒绝访问,当用户attemps访问过他们拥有完全控制的文件夹例外。

Today we deployed our newly created ASP.NET application to the server and soon we realized there was a strange security-related issue which was causing the application to crash. This is an internal application and we use Impersonation to manage how the users access resources. The application however, throws an "Access Denied" exception when the user attemps to access a folder over which they have full control.

唯一的例外是实际上是一个 AggregateException 并在其中使用 Parallel.ForEach 来枚举列表的方法和体内被抛出,它试图访问该文件夹,但在这一点上模拟环境得到改变,工人线程运行的应用程序池的身份,它没有进入,因此该文件夹的除外。

The exception was in fact an AggregateException and was being thrown in a method which uses Parallel.ForEach to enumerate over a list and inside the body, it attempts to access the folder, but at this point the Impersonation Context gets changed and the worker thread runs as the application pool's identity, which doesn't have access to the folder hence the exception.

为了证实这一点,我看着进程标识前, Parallel.ForEach 的身体里面:

To confirm this, I looked at the process identity before and inside the body of Parallel.ForEach:

string before = WindowsIdentity.GetCurrent().Name;
Debug.WriteLine("Before Loop: {0}", before);

Parallel.ForEach(myList, currentItem =>
{
    string inside = WindowsIdentity.GetCurrent().Name;
    Debug.WriteLine("Inside Loop: {0} (Worker Thread {1})", inside, Thread.CurrentThread.ManagedThreadId);
});

当我运行的应用程序,这就是被打印出来:

When I run the app, this is what gets printed out:

Before Loop: MyDomain\ImpersonatedUser

Inside Loop: NT AUTHORITY\SYSTEM (Worker Thread 8)
Inside Loop: MyDomain\ImpersonatedUser (Worker Thread 6)
Inside Loop: MyDomain\ImpersonatedUser (Worker Thread 7)
Inside Loop: NT AUTHORITY\SYSTEM (Worker Thread 9)
Inside Loop: NT AUTHORITY\SYSTEM (Worker Thread 10)
Inside Loop: MyDomain\ImpersonatedUser (Worker Thread 7)
Inside Loop: MyDomain\ImpersonatedUser (Worker Thread 6)
Inside Loop: MyDomain\ImpersonatedUser (Worker Thread 7)

正如你所看到的,某些线程运行的模拟标识有的作为应用程序池(在这种情况下,本地系统),并似乎没有成为一个模式。在调用堆栈窗口中的前一帧也变为非托管 KERNEL32.DLL ,这让我觉得CLR ISN ŧ验证它委托给操作系统之前的环境。

As you can see, some threads are running as the impersonated identity and some as the application pool (in this case, LocalSystem) and there doesn't seem to be a pattern. The previous frame in the Call Stack window also goes to the unmanaged kernel32.dll, which makes me think CLR isn't validating the context before delegating it to the OS.

任何想法,为什么会这样?那是一个已知的问题/错误?

Any idea why this is happening? Is that a known issue/bug?

推荐答案

不像工作类,并行似乎并没有被捕获的ExecutionContext 您目前正在运行(这反过来抓住了 SecurityContext的持有的的WindowsIdentity )。它使用当前线程内一个avaliable

Unlike the Task class, Parallel doesn't seem to be capturing the ExecutionContext you're currently running on (which in turns captures the SecurityContext which holds the WindowsIdentity). It uses the one avaliable inside the current Thread.

您必须明确地捕捉到想要的背景:

You have to explicitly capture the desired context:

IntPtr token = WindowsIdentity.GetCurrent().Token;

Parallel.ForEach(myList, currentItem =>
{
   using (WindowsIdentity.Impersonate(token))
   {
      string inside = WindowsIdentity.GetCurrent().Name;
      Debug.WriteLine("Inside Loop: {0} (Worker Thread {1})", inside, Thread.CurrentThread.ManagedThreadId);
   }
});

这篇关于Parallel.ForEach()更改模拟环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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