4

我有一个调用 SQL 存储过程的 WCF 服务方法。我正在使用 IIS 5 进行开发(对此无能为力,II6/7 不可用)

为了获得一些收益,我通过将调用放入 ac# TPL Task 中对该存储过程进行了多次异步调用。

作为任务运行时,我收到 SQL 异常...“登录失败。登录来自不受信任的域,不能用于 Windows 身份验证”

但是,如果我在不使用任务的情况下运行完全相同的进程,则 SQL 连接没有问题

在我看来,IIS 虚拟文件夹 (WCF) 的凭据没有被委派给任务?有什么想法可以为 TPL 任务线程指定凭据,即使用与父级相同的凭据等吗?

我正在使用 Windows 身份验证 (sspi) 和模拟,以便能够连接到单独的 SQL 框。

感谢您的帮助。

4

2 回答 2

5

你有两个选择。

1)选择您的整个应用程序始终使用以下方式流动身份:

<runtime>
    <alwaysFlowImpersonationPolicy enabled="true"/>
</runtime>

这会产生开销的副作用,并且存在使用当前调用用户的权限而不是应用程序身份意外执行某些意外代码的危险。我个人会避免这种情况,并使用您明确选择加入的#2。

WindowsIdentity2)在设置您的 TPL 任务之前捕获并明确模拟您需要使用Impersonate+拨打电话的位置WindowsImpersonationContext

public void SomeWCFOperation()
{
    WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();

    Task.Factory.StartNew(() =>
    {
         // some unpriviledged code here


         using(WindowsImpersonationContext impersonationContext = currentIdentity.Impersonate())
         {
            // this code will execute with the priviledges of the caller
         }

         // some more unpriviledged code here
    });  
}
于 2012-04-06T16:03:17.850 回答
0

作为另一种解决方法,您可以为 TPL 创建扩展,如下所示:

public static class TaskFactoryExtensions
{
    public static Task StartNewImpersonated(this TaskFactory taskFactory, Action action)
    {
        var identity = WindowsIdentity.GetCurrent();
        return taskFactory.StartNew(() =>
        {
            using (identity.Impersonate()) 
            {
                action();
            }
        });
    }

    public static Task<TResult> StartNewImpersonated<TResult>(this TaskFactory taskFactory, Func<TResult> function)
    {
        var identity = WindowsIdentity.GetCurrent();
        return taskFactory.StartNew<TResult>(() =>
        {
            using (identity.Impersonate())
            {
                return function();
            }
        });
    }
}

然后,您将调用这些新方法来代替标准的 StartNew 方法。

这样做的缺点是有很多方法可以覆盖。

于 2012-08-30T14:31:29.837 回答