This week I ran into a very strange issue that has some pretty big implications.
The problem is this: if you use
ASP.NET with impersonation, and you also use Parallel.ForEach, threads that run on other cores, lose the execution context.
Put another way, threads that run on other cores don’t respect your impersonation settings, and default to the unimpersonated calling context.
How to reproduce:
First, add impersonation to the web.config (within <system.web>) – for example:
<identity impersonate=“true“
userName=“mydomain\MyServiceAccount“
password=“GoodPassword“/>
Now, in code, I run this code synchronously:
protected void Page_Load(object sender, EventArgs e)
{
Debug.WriteLine(“Process starting as “ + WindowsIdentity.GetCurrent().Name);
List<String> items = new List<string>();
items.Add(“Item 1″);
items.Add(“Item 2″);
items.Add(“Item 3″);
items.Add(“Item 4″);
items.Add(“Item 5″);
items.Add(“Item 6″);
items.Add(“Item 7″);
foreach (String item in items)
{
DoWork(item);
}
}
private void DoWork(String itemName)
{
DebuWriteLine(“Executing “ + itemName + ” as “ + WindowsIdentity.GetCurrent().Name);
}
That results in output, like you might think:
Process starting as myDomain\MyServiceAccount
Executing Item 1 as myDomain\MyServiceAccount
Executing Item 2 as myDomain\MyServiceAccount
Executing Item 3 as myDomain\MyServiceAccount
Executing Item 4 as myDomain\MyServiceAccount
Executing Item 5 as myDomain\MyServiceAccount
Executing Item 6 as myDomain\MyServiceAccount
Executing Item 7 as myDomain\MyServiceAccount
Now, if you instead run that code as a Parallel.ForEach:
Parallel.ForEach(items, (item) =>
{
DoWork(item);
});
You will then see very strange results:
Process starting as myDomain\MyServiceAccount
Executing Item 2 as myDomain\rseder
Executing Item 1 as myDomain\MyServiceAccount
Executing Item 3 as myDomain\rseder
Executing Item 4 as myDomain\MyServiceAccount
Executing Item 6 as myDomain\MyServiceAccount
Executing Item 5 as myDomain\rseder
Executing Item 7 as myDomain\MyServiceAccount
What is happening? I’m not exactly sure. I read quite a few message board comments of people guessing. I spent a whole afternoon going to a zillion different pages, sorry I don’t have anything specific to reference here.
Anyhow, this code ran on a single processor, quad-core computer. It seems as though when code runs on the other cores, it loses execution context.
A Solution, not a great one though:
One solution I found (again, sorry, I couldn’t find link to credit the original idea) was to RE-impersonate the impersonated user, within our Parallel.ForEach. That looks something like this:
// Get a handle to the current, impersonated identity
WindowsIdentity identity = WindowsIdentity.GetCurrent();
Parallel.ForEach(items, (item) =>
{
// RE-impersonate the
ASP.NET identity, within this separate task
using (WindowsImpersonationContext impersonationContext =
identity.Impersonate())
Posted via email from Jasper-net