Per l'autenticazione di base che ho implementato un personalizzato HttpMessageHandler
sull'esempio mostrato nella risposta di Darin Dimitrov qui: https://stackoverflow.com/a/11536349/270591Come posso impostare in modo sicuro l'utente principale in un WebAPI personalizzato HttpMessageHandler?
Il codice crea un'istanza principal
di tipo GenericPrincipal
con nome utente e ruoli e quindi imposta questo principio alla principale corrente del filo:
Thread.CurrentPrincipal = principal;
seguito in un metodo ApiController
il principale può essere letta mediante l'accesso alla controllori User
proprietà:
public class ValuesController : ApiController
{
public void Post(TestModel model)
{
var user = User; // this should be the principal set in the handler
//...
}
}
Questo sembrava funzionare benissimo fino a che recentemente aggiunto un personalizzato MediaTypeFormatter
che utilizza la libreria Task
in questo modo:
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;
}
(ho questo approccio per iniziare un'attività con Task.Factory.StartNew
in ReadFromStreamAsync
da alcuni esempi di codice. È sbagliato e forse l'unica ragione del problema?)
Ora, "a volte" - e per me sembra essere casuale - il principal User
nel metodo controller non è più il principal che ho impostato in MessageHandler, ovvero nome utente, flag e tutti i ruoli vengono persi. Il motivo sembra essere che il MediaTypeFormatter personalizzato provoca una modifica del thread tra MessageHandler e il metodo controller. L'ho confermato confrontando i valori di Thread.CurrentThread.ManagedThreadId
nel MessageHandler e nel metodo del controller. "A volte" sono diversi e quindi il principale è "perso".
Ho guardato ora un'alternativa all'impostazione Thread.CurrentPrincipal
per trasferire in qualche modo il capitale in modo sicuro dal messageHandler personalizzato al metodo di controllo e in this blog post proprietà delle richieste sono utilizzati:
request.Properties.Add(HttpPropertyKeys.UserPrincipalKey,
new GenericPrincipal(identity, new string[0]));
ho voluto mettere alla prova questo, ma sembra che la classe HttpPropertyKeys
(che si trova nello spazio dei nomi System.Web.Http.Hosting
) non abbia più una proprietà UserPrincipalKey
nelle versioni WebApi recenti (release candidate e versione finale della scorsa settimana).
La mia domanda è: come posso modificare l'ultimo frammento di codice sopra in modo che funzioni con la versione WebAPI corrente? O in generale: come posso impostare l'utente principale in un MessageHandler personalizzato e accedervi in modo affidabile in un metodo di controllo?
Modifica
È menzionato here che "HttpPropertyKeys.UserPrincipalKey
... decide di “MS_UserPrincipal”
", così ho cercato di usare:
request.Properties.Add("MS_UserPrincipal",
new GenericPrincipal(identity, new string[0]));
Ma non funziona come mi aspettavo: la La proprietà ApiController.User
non contiene il principal aggiunto alla raccolta Properties
sopra.
Suggerisco di guardare questo https://github.com/thinktecture/Thinktecture.IdentityModel.45 –