我希望你能帮助我。
我正在我的 C# 4.0 应用程序中执行一些需要身份验证的网络请求。我只是使用CredentialsCache.DefaultCredentials
. 只要我不在不同的线程/任务中通过Task<T>.Factory.StartNew(...)
. 然后我得到401错误。我假设凭据没有传递给子线程?
如何将凭据传递给任何子任务/线程?
我希望你能帮助我。
我正在我的 C# 4.0 应用程序中执行一些需要身份验证的网络请求。我只是使用CredentialsCache.DefaultCredentials
. 只要我不在不同的线程/任务中通过Task<T>.Factory.StartNew(...)
. 然后我得到401错误。我假设凭据没有传递给子线程?
如何将凭据传递给任何子任务/线程?
我假设您正在使用模拟,问题是凭据没有流入任务。值得检查这一点,通过转储Windows.Identity.GetCurrent().Name
启动代码和任务主体中的值并确保它是您所期望的,以节省大麻烦。
因此,鉴于上述情况,有几种方法(正式地说)执行上下文(或只是安全上下文)不会跨线程流动。默认行为是上下文是流动的 - 所以一定有什么影响它。
1) 某些东西已经设置ExecutionContext.SuppressFlow()
- 您可以通过转储ExecutionContext.IsFlowSuppressed()
任务内部的值来检查这一点。
2) 有一个配置元素<legacyImpersonationPolicy>
(conifguration->runtime->legacyImpersonationPolicy),默认为false
. 当 时,false
WindowsIdentity流经异步点。当它不是。这与 ExecutionContext 流设置无关。所以这里会给你带来问题。您可以通过转储is your task 的值来检查这一点。这也可以通过每个线程以编程方式设置。true
true
SecurityContext.IsWindowsIdentityFlowSuppressed()
SecurityContext.SuppressFlowWindowsIdentity()
最后,为了完整起见,如果您使用的是非托管代码,还有另一个设置<alwaysFlowImpersonationPolicy>
可以控制模拟凭据在非托管场景中的流动方式;描述的其他设置仅影响托管代码。
万一其他人遇到这个问题......我的有点不同。我的 WCF 服务作为 REST 服务和 SOAP 公开,其安全上下文来自 System.Web.HttpContext.Current 或 System.ServiceModel.OperationContext.Current。我的 DAL 使用这些上下文之一通过检查 HttpContext.Current.User.Identity 或 OperationContext.Current.ClaimsPrincipal.Identity 来识别当前用户。
因此,就我而言,我必须将这两个上下文保存在并行 foreach 之外的变量中,然后将它们设置为与保存的值并行的内部。这似乎奏效了。相同的概念可以通过一些修改适用于其他 TPL 情况。
var httpcontext = System.Web.HttpContext.Current;
var opcontext = System.ServiceModel.OperationContext.Current;
Parallel.ForEach(types, (p) =>
{
System.Web.HttpContext.Current = httpcontext;
System.ServiceModel.OperationContext.Current = opcontext;
// DO YOUR PARALLEL PROCESSING HERE
});