【发布时间】:2012-08-15 05:58:08
【问题描述】:
对于基本身份验证,我根据 Darin Dimitrov 的回答中显示的示例实现了自定义 HttpMessageHandler:https://stackoverflow.com/a/11536349/270591
代码使用用户名和角色创建GenericPrincipal 类型的实例principal,然后将此主体设置为线程的当前主体:
Thread.CurrentPrincipal = principal;
稍后在ApiController 方法中,可以通过访问控制器User 属性来读取主体:
public class ValuesController : ApiController
{
public void Post(TestModel model)
{
var user = User; // this should be the principal set in the handler
//...
}
}
这似乎工作正常,直到我最近添加了一个使用 Task 库的自定义 MediaTypeFormatter,如下所示:
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream,
HttpContent content, IFormatterLogger formatterLogger)
{
var task = Task.Factory.StartNew(() =>
{
// some formatting happens and finally a TestModel is returned,
// simulated here by just an empty model
return (object)new TestModel();
});
return task;
}
(我有这种方法可以通过一些示例代码在ReadFromStreamAsync 中使用Task.Factory.StartNew 开始任务。这是错误的,也许是问题的唯一原因?)
现在,“有时”——对我来说似乎是随机的——控制器方法中的 User 主体不再是我在 MessageHandler 中设置的主体,即用户名、Authenticated 标志和角色全部丢失。原因似乎是自定义 MediaTypeFormatter 导致 MessageHandler 和控制器方法之间的线程发生变化。我通过比较 MessageHandler 和控制器方法中的 Thread.CurrentThread.ManagedThreadId 的值来确认这一点。 “有时”它们是不同的,然后主体就“丢失”了。
我现在正在寻找一种替代方法来设置 Thread.CurrentPrincipal 以某种方式将主体从自定义 MessageHandler 安全地传输到控制器方法,并在 this blog post 中使用请求属性:
request.Properties.Add(HttpPropertyKeys.UserPrincipalKey,
new GenericPrincipal(identity, new string[0]));
我想对此进行测试,但似乎 HttpPropertyKeys 类(位于命名空间 System.Web.Http.Hosting 中)在最近的 WebApi 版本中不再具有 UserPrincipalKey 属性(候选版本和上周的最终版本)以及)。
我的问题是:如何更改上面的最后一个代码 sn-p 以便与当前的 WebAPI 版本一起使用?或者一般来说:如何在自定义 MessageHandler 中设置用户主体并在控制器方法中可靠地访问它?
编辑
提到here,“HttpPropertyKeys.UserPrincipalKey ...解析为“MS_UserPrincipal””,所以我尝试使用:
request.Properties.Add("MS_UserPrincipal",
new GenericPrincipal(identity, new string[0]));
但它并没有像我预期的那样工作:ApiController.User 属性不包含添加到上面Properties 集合中的主体。
【问题讨论】:
标签: asp.net .net asp.net-mvc security asp.net-web-api