Thread.CurrentPrincipal has some problems in certain threading/parallelism situations.
That's why it is not used anymore in Web API v2. Use the GetRequestContext() extension method on HttpRequestMessage to get to the current user / or setting it
题
At the beginning of each request, I set the Thread.CurrentPrincipal in my AuthorizationFilter to the authenticated user with custom claims. When I try to log errors thrown in a controller action in my ExceptionFilter, the principal accessed from within the ExceptionFilter isn't the same as the one I set in my AuthorizationFilter. In fact, the principal I get in the ExceptionFilter is the principal that existed on the thread before I changed it in my AuthorizationFilter. After browsing the source code of Web API, I think I found the problem which is related to the execution context of tasks (see the ApiController class, ExecuteAsync method). The sample code below is a simple way to reproduce the problem:
class Program
{
static void Main(string[] args)
{
SetIdentity("originIdentity");
Func<Task> controllerAction = () =>
{
Console.WriteLine("Identity is correct in controller: " + Thread.CurrentPrincipal.Identity.Name);
return Task.FromResult("result");
};
Func<Task> authFilter = async () =>
{
SetIdentity("newIdentity");
Console.WriteLine("Set identity to " + Thread.CurrentPrincipal.Identity.Name);
await controllerAction();
};
Func<Task> exceptionFilter = async () =>
{
Console.WriteLine("Original identity: " + Thread.CurrentPrincipal.Identity.Name);
//there would be a try block around this so we can catch exceptions
await authFilter();
Console.WriteLine("Identity is what it was before: " + Thread.CurrentPrincipal.Identity.Name);
};
exceptionFilter().Wait();
Console.Read();
}
private static void SetIdentity(string originidentity)
{
var originIdentity = new ClaimsIdentity("HeaderAuthentication");
originIdentity.AddClaim(new Claim(ClaimTypes.Name, originidentity));
Thread.CurrentPrincipal = new ClaimsPrincipal(originIdentity);
}
}
And output:
Original identity: originIdentity
Set identity to newIdentity
Identity is correct in controller: newIdentity
Identity is what it was before: originIdentity
My questions are:
解决方案
Thread.CurrentPrincipal has some problems in certain threading/parallelism situations.
That's why it is not used anymore in Web API v2. Use the GetRequestContext() extension method on HttpRequestMessage to get to the current user / or setting it