¿Cómo puedo configurar de forma segura el principal de usuario en un WebAPI HttpMessageHandler personalizado?
Para la autenticación básica he implementado una personalizada.HttpMessageHandler
basado en el ejemplo mostrado en la respuesta de Darin Dimitrov aquí:https://stackoverflow.com/a/11536349/270591
El código crea una instancia.principal
de tipoGenericPrincipal
con nombre de usuario y roles y luego establece este principal al principal actual del hilo:
Thread.CurrentPrincipal = principal;
Mas tarde en unApiController
Método que el director puede leer accediendo a los controladoresUser
propiedad:
public class ValuesController : ApiController
{
public void Post(TestModel model)
{
var user = User; // this should be the principal set in the handler
//...
}
}
Esto pareció funcionar bien hasta que recientemente agregué una personalizadaMediaTypeFormatter
que usa elTask
biblioteca como tal:
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;
}
(Tengo este enfoque para comenzar una tarea conTask.Factory.StartNew
enReadFromStreamAsync
de algún código de ejemplo. ¿Está mal y quizás la única razón del problema?)
Ahora, "a veces" - y para mí parece ser aleatorio - elUser
el principal en el método del controlador ya no es el principal que he establecido en MessageHandler, es decir, el nombre de usuario,Authenticated
La bandera y los roles están todos perdidos. El motivo parece ser que el MediaTypeFormatter personalizado provoca un cambio en el hilo entre MessageHandler y el método del controlador. He confirmado esto comparando los valores deThread.CurrentThread.ManagedThreadId
en el MessageHandler y en el método del controlador. "A veces" son diferentes y luego el principal se "pierde".
He buscado ahora una alternativa a la configuraciónThread.CurrentPrincipal
de alguna manera transferir el principal de forma segura desde el MessageHandler personalizado al método del controlador y enesta entrada de blog Se utilizan propiedades de solicitud:
request.Properties.Add(HttpPropertyKeys.UserPrincipalKey,
new GenericPrincipal(identity, new string[0]));
Quería probar eso pero parece que laHttpPropertyKeys
clase (que está en el espacio de nombresSystem.Web.Http.Hosting
) no tiene unUserPrincipalKey
propiedad ya en las versiones recientes de WebApi (versión candidata y versión final de la semana pasada).
Mi pregunta es: ¿Cómo puedo cambiar el último fragmento de código de arriba para que funcione con la versión actual de WebAPI? O, en general, ¿cómo puedo configurar el principal de usuario en un MessageHandler personalizado y acceder de manera confiable en un método de controlador?
Editar
Se mencionaaquí ese "HttpPropertyKeys.UserPrincipalKey
... se resuelve“MS_UserPrincipal”
", así que traté de usar:
request.Properties.Add("MS_UserPrincipal",
new GenericPrincipal(identity, new string[0]));
Pero no funciona como esperaba: laApiController.User
propiedad no contiene el principal agregado a laProperties
colección de arriba