【发布时间】:2013-05-09 06:52:37
【问题描述】:
使用 ASP.NET WebAPI,在身份验证期间设置Thread.CurrentPrincipal,以便控制器以后可以使用ApiController.User 属性。
如果该身份验证步骤变为异步(咨询另一个系统),CurrentPrincipal 的任何突变都会丢失(当调用者的 await 恢复同步上下文时)。
这是一个非常简化的示例(在实际代码中,身份验证发生在操作过滤器中):
using System.Diagnostics;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
public class ExampleAsyncController : System.Web.Http.ApiController
{
public async Task GetAsync()
{
await AuthenticateAsync();
// The await above saved/restored the current synchronization
// context, thus undoing the assignment in AuthenticateAsync().
Debug.Assert(User is GenericPrincipal);
}
private static async Task AuthenticateAsync()
{
// Save the current HttpContext because it's null after await.
var currentHttpContext = System.Web.HttpContext.Current;
// Asynchronously determine identity.
await Task.Delay(1000);
var identity = new GenericIdentity("<name>");
var roles = new string[] { };
Thread.CurrentPrincipal = new GenericPrincipal(identity, roles);
currentHttpContext.User = Thread.CurrentPrincipal;
}
}
如何在异步函数中设置 Thread.CurrentPrincipal 以使调用者的 await 在恢复同步上下文时不会丢弃该突变?
【问题讨论】:
-
我不确定您的问题,但理想情况下,最好在调用控制器之前对其进行身份验证。在我的 WebAPI 项目中,我喜欢设置一个
DelegatingHandler,它会在到达控制器之前进行身份验证。 -
@Matthew,我同意,这就是真实代码的工作方式,动作过滤器在调用控制器方法之前处理身份验证。我排除了操作过滤器以简化我的示例,但在任何一种情况下问题都是相同的。
-
从这个 stackoverflow 答案看来,如果您设置 CurrentPrincipal,它将持续到调用线程:stackoverflow.com/a/12460170/507793,否则我不确定如何解决您的问题。
标签: c# asp.net-web-api async-await