Для базовой проверки подлинности я реализовал пользовательский HttpMessageHandler
на примере, показанном в Дарине Димитров, здесь: qaru.site/info/114619/...
Код создает экземпляр principal
типа GenericPrincipal
с именем пользователя и ролями, а затем устанавливает этот принцип в текущий принцип потока:
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
//...
}
}
Казалось, что это нормально, пока я недавно не добавил пользовательский MediaTypeFormatter
, который использует библиотеку Task
следующим образом:
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;
}
(У меня есть такой подход, чтобы запустить задачу с Task.Factory.StartNew
в ReadFromStreamAsync
из некоторого примера кода. Это неправильно и, возможно, единственная причина проблемы?)
Теперь "иногда" - и для меня это кажется случайным - принцип User
в методе контроллера больше не является основным, который я установил в MessageHandler, то есть имя пользователя, Authenticated
и роли потеряны. Причина в том, что пользовательский MediaTypeFormatter вызывает изменение потока между MessageHandler и методом контроллера. Я подтвердил это, сравнив значения Thread.CurrentThread.ManagedThreadId
в MessageHandler и в методе контроллера. "Иногда" они разные, а затем "потеряно".
Теперь я искал альтернативу настройке Thread.CurrentPrincipal
, чтобы как-то передать принципала безопасно из пользовательского MessageHandler в метод контроллера и в этот блог post:
request.Properties.Add(HttpPropertyKeys.UserPrincipalKey,
new GenericPrincipal(identity, new string[0]));
Я хотел проверить это, но кажется, что класс HttpPropertyKeys
(который находится в пространстве имен System.Web.Http.Hosting
) больше не имеет свойства UserPrincipalKey
в последних версиях WebApi (релиз-кандидат и окончательный выпуск с прошлой недели также).
Мой вопрос: как я могу изменить последний фрагмент кода выше, чтобы он работал с текущей версией WebAPI? Или вообще: как я могу установить пользовательский принцип в пользовательском MessageHandler и надежно получить его в методе контроллера?
Edit
Здесь упоминается , что "HttpPropertyKeys.UserPrincipalKey
... разрешает "MS_UserPrincipal"
", поэтому я попытался использовать:
request.Properties.Add("MS_UserPrincipal",
new GenericPrincipal(identity, new string[0]));
Но он не работает так, как я ожидал: свойство ApiController.User
не содержит принципала, добавленного в коллекцию Properties
выше.