在调用Task.WaitAll()时,如何设置任务的用户身份标识?

9
我在同时调用WCF服务时遇到了问题。我尝试使用Tasks来并行调用两个服务以节省时间(我不想将此设置为异步),但我的任务是以另一个用户运行的。由于调用服务的用户没有所需权限,因此两个服务的调用都失败了,这是由于两个服务都需要Windows身份验证。
下面的调用代码位于ASP.NET MVC4控制器操作内,在IIS 7.5上运行。所有涉及的应用程序池都设置为允许ASP.NET模拟和需要Windows身份验证(所有其他方法均设置为禁用)。
// 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);

我的问题:如何指示任务以当前用户的身份运行,而不是作为"IIS APPPOOL\DefaultAppPool"用户运行?


大多数由IIS运行的服务代码都使用专门的用户帐户运行。有什么理由打破沙盒以另一个用户身份运行它吗?这不是文件访问功能... - Alex F
1
Jasper: 我所调用的服务都使用Kerberos / Windows身份验证,并要求客户端经过身份验证和授权(通过AD角色)才能使用它。这就是为什么我必须使用正确的凭据来调用它们的原因。 - Valdemar
2个回答

14

试一试:

WindowsIdentity impersonatedUser = WindowsIdentity.GetCurrent();

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

这是我最终采用的解决方案。有点额外开销,但能胜任工作。 - Valdemar

4
您可能需要研究一下是否设置<alwaysFlowImpersonationContext>是合适的:

指定Windows标识始终在异步点之间流动,无论如何执行模拟。

默认情况下,在ASP.Net中,此设置处于关闭状态,因此任务(可能在其他线程上运行)最终只是以没有模拟的方式运行。
否则(如果不适合设置),我认为您可以将WindowsIdentity对象捕获到由Task捕获的局部变量中,然后从任务内部调用Impersonate()。(尽管我没有尝试过这个方法)

明天我会在工作中尝试使用alwaysFlowImpersonationPolicy,它似乎是我一直在寻找的解决方案。 - Valdemar
看起来我需要在 aspnet.config 文件中添加 alwaysFlowImpersonationPolicy 元素,该文件是整个服务器的全局文件,因此这不是一个选项。 - Valdemar
alwaysFlowImpersonationContext现在可以按应用程序池进行配置。https://weblogs.asp.net/owscott/setting-an-aspnet-config-file-per-application-pool - Lord Darth Vader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接