How do I set the user identity for tasks when call

2019-01-15 08:40发布

问题:

I'm having a problem invoking WCF services in parallel. I'm trying to use Tasks to invoke two services in parallel to save some time (I'm NOT trying to make this async), but my tasks are being run as another user. Both services require Windows authentication and both calls fail because the user invoking the service does not have the required permissions.

The calling code (code below) is located inside a Controller Action in ASP.NET MVC4, running IIS 7.5. All application pools involved are set to allow ASP.NET Impersonation and require Windows Authentication (all other methods set to disabled).

// Parallel service request to two services
Task<object>[] tasks = new Task<object>[2];

// this shows my credentials, e.g. "MYDOMAIN\\MyUsername"
var userMe = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

tasks[0] = Task<object>.Factory.StartNew(() => 
{
    // this shows "IIS APPPOOL\\DefaultAppPool"
    var user = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

    var data = client1.MyMethod();
    return data;
});

tasks[1] = Task<object>.Factory.StartNew(() =>
{
    // this shows "IIS APPPOOL\\DefaultAppPool"
    var user = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

    var data = client2.MyMethod();
    return data;
});

Task.WaitAll(tasks);

My problem: How do I instruct the tasks to run as the current user, instead of running as the "IIS APPPOOL\DefaultAppPool" user?

回答1:

Try this:

WindowsIdentity impersonatedUser = WindowsIdentity.GetCurrent();

Task<object>.Factory.StartNew(() =>
{
    using (WindowsImpersonationContext ctx = impersonatedUser.Impersonate())
    {
       //Your code
    }
    return data;
});


回答2:

You might want to look into whether setting <alwaysFlowImpersonationContext> is appropriate:

Specifies that the Windows identity always flows across asynchronous points, regardless of how impersonation was performed.

By default, this setting is off within ASP.Net, and so the tasks (running, potentially, on other threads) end up just running with no impersonation in place.

Otherwise (if it's not appropriate to set that), I think you could capture the WindowsIdentity object into a local variable that's captured by the Tasks, and then call Impersonate() on it from within the task. (although I haven't tried this)