【发布时间】:2014-04-17 20:36:41
【问题描述】:
在每个请求开始时,我将 AuthorizationFilter 中的 Thread.CurrentPrincipal 设置为具有自定义声明的经过身份验证的用户。当我尝试在 ExceptionFilter 中记录控制器操作中引发的错误时,从 ExceptionFilter 中访问的主体与我在 AuthorizationFilter 中设置的主体不同。事实上,我在 ExceptionFilter 中获得的主体是在我在 AuthorizationFilter 中更改它之前存在于线程上的主体。浏览 Web API 的源代码后,我想我发现了与任务执行上下文有关的问题(参见 ApiController 类,ExecuteAsync 方法)。下面的示例代码是重现问题的简单方法:
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);
}
}
然后输出:
Original identity: originIdentity
Set identity to newIdentity
Identity is correct in controller: newIdentity
Identity is what it was before: originIdentity
我的问题是:
- 我看到的是我认为我看到的吗?
- 这是一个错误还是 Web API 中的设计? TPL 以这种方式运行是有道理的,但很难想象这是 Web API 中的预期行为
- 在 Web API 中解决此问题的推荐/干净方法是什么?
【问题讨论】:
标签: logging exception-handling asp.net-web-api task-parallel-library