Async await 安全性、Thread.CurrentPrincipal和ConfigureAwait(false)

Async await 安全性、Thread.CurrentPrincipal和ConfigureAwait(false),async-await,claims-based-identity,synchronizationcontext,executioncontext,current-principal,Async Await,Claims Based Identity,Synchronizationcontext,Executioncontext,Current Principal,在使用ConfigureWait(false)的引用库中使用Thread.CurrentPrincipal的声明是否会带来任何问题,或者ExecutionContext的逻辑调用上下文的流动是否会解决这些问题?(到目前为止,我的阅读和测试表明它会) WebAPI控制器操作示例: [CustomAuthorizationThatSetsCurrentUsersClaimstoThreadCurrentContextandHttpContextCurrentUser] 公共异步任务Get(int-o

在使用ConfigureWait(false)的引用库中使用Thread.CurrentPrincipal的声明是否会带来任何问题,或者ExecutionContext的逻辑调用上下文的流动是否会解决这些问题?(到目前为止,我的阅读和测试表明它会)

WebAPI控制器操作示例:

[CustomAuthorizationThatSetsCurrentUsersClaimstoThreadCurrentContextandHttpContextCurrentUser]
公共异步任务Get(int-orderId)
{
return await _orderBusinessLogicLibrary.LoadAsync(orderId);//默认为.ConfigureAwait(true)
}
从外部引用库加载函数示例:

[ClaimsPrincipalPermission(
安全行动,要求,
Operation=“Read”,
Resource=“订单”)]
[索赔]触诊(
安全行动,要求,
Operation=“Read”,
Resource=“OrderItems”)]
公共异步任务加载(int orderId)
{
var order=await\u repository.LoadOrderAsync(orderId).ConfigureAwait(false);
//这是关键一点。假设这个较低级别的函数也是强制的
//与此方法相同的安全约束将
//Thread.CurrentPrincipal在下面的函数中是否仍然正确?
order.Items=await\u repository.LoadOrderItemsAsync(orderId).ConfigureAwait(false);
退货单;
}

而且,答案不能是“那么就不要使用configurewait(false)!”。这可能会导致其他问题,例如死锁()。

从我的测试中,似乎
线程.CurrentPrincipal
将正确流动,即使您使用
配置等待(false)
。下面的WebAPI代码设置主体,然后阻塞
async
调用,强制另一个线程恢复
async
方法。另一个线程确实继承了正确的主体

private async Task async()
{
等待任务。延迟(1000)。配置等待(false);
返回“Thread”+Thread.CurrentThread.ManagedThreadId+”:“+Thread.CurrentPrincipal.Identity.Name+”\n”;
}
公共字符串Get(int-id)
{
var user=新索赔实体(新索赔实体)(
新[]
{
新索赔(ClaimTypes.Name,“Bob”),
}
));
HttpContext.Current.User=用户;
Thread.CurrentPrincipal=用户;
var ret=“Thread”+Thread.CurrentThread.ManagedThreadId+”:“+Thread.CurrentPrincipal.Identity.Name+”\n”;
ret+=Async().Result;
返回ret;
}
当我在IISExpress的新实例上运行此代码时,我得到:

"Thread 7: Bob\nThread 6: Bob\n"

但是,我应该指出,不建议使用
ConfigureAwait(false)
来避免死锁。在ASP.NET上尤其如此。如果可能,请始终使用
configurewait(false)
async
。请注意,WebAPI是一个完全异步的堆栈,您应该能够做到这一点。

太好了,我也看到了同样的结果。有一个问题需要澄清——您最后一次关于不使用
ConfigureAwait(false)
来避免死锁的评论是针对使用.Result来阻止异步方法的,对吗?因此,您不应该从
ConfigureAwait(true)
切换到
ConfigureAwait(false)
要修复死锁,您应该使整个堆栈完全异步,并且仍然需要
ConfigureAwait(true)ASP.NET上的
等待以完全还原HttpContext等等。@MichaelRotter:ConfigureAwait的默认值为
true
。因此,如果您的
async
方法需要上下文,它就不应该使用
ConfigureAwait
。如果不需要上下文,则应使用
ConfigureAwait(false)
。我建议使整个堆栈
异步
,并在任何不需要上下文的方法上使用
ConfigureAwait(false)