Ich muss sagen, dass ich ziemlich überrascht war, dass HttpContext im Konstruktor null ist. Ich bin sicher, es ist aus Leistungsgründen. Habe bestätigt, dass die Verwendung IPrincipalwie unten beschrieben in den Konstruktor injiziert wird. Es macht im Wesentlichen das Gleiche wie die akzeptierte Antwort, aber auf eine andere Art und Weise.
Für alle, die diese Frage finden und nach einer Antwort auf das allgemeine "Wie bekomme ich den aktuellen Benutzer?" Suchen. Sie können einfach Userdirekt von zugreifen Controller.User. Sie können dies jedoch nur innerhalb von Aktionsmethoden tun (ich gehe davon aus, dass Controller nicht nur mit HttpContexts und aus Leistungsgründen ausgeführt werden).
Wenn Sie es jedoch im Konstruktor benötigen (wie es OP getan hat) oder andere injizierbare Objekte erstellen müssen, die den aktuellen Benutzer benötigen, ist das Folgende ein besserer Ansatz:
Injizieren Sie IPrincipal, um den Benutzer zu erhalten
Erstes Treffen IPrincipalundIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipalund IIdentityrepräsentiert den Benutzer und den Benutzernamen. Wikipedia wird Sie trösten, wenn "Principal" seltsam klingt .
Wichtig zu erkennen , dass , ob Sie es aus IHttpContextAccessor.HttpContext.User, ControllerBase.Useroder ControllerBase.HttpContext.UserSie bekommen ein Objekt , das eine sein , garantiert ClaimsPrincipalObjekt , das implementiertIPrincipal .
Es gibt derzeit keinen anderen Benutzertyp, den ASP.NET verwendet User(aber das heißt nicht, dass etwas anderes nicht implementiert werden kann IPrincipal).
Wenn Sie also etwas haben, das von 'dem aktuellen Benutzernamen' abhängt, den Sie injizieren möchten, sollten Sie injizieren IPrincipalund definitiv nicht IHttpContextAccessor.
Wichtig: Verschwenden Sie keine Zeit damit, IPrincipaldirekt in Ihren Controller oder Ihre Aktionsmethode zu injizieren - dies ist sinnlos, da Useres Ihnen dort bereits zur Verfügung steht.
In startup.cs:
// Inject IPrincipal
services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
Dann in Ihr DI-Objekt, das den Benutzer benötigt, injizieren Sie einfach, IPrincipalum den aktuellen Benutzer zu erhalten.
Das Wichtigste dabei ist, wenn Sie Unit-Tests durchführen, müssen Sie keine senden HttpContext, sondern nur etwas verspotten, das darstellt, IPrincipal was einfach sein kann ClaimsPrincipal .
Eine besonders wichtige Sache, bei der ich mir nicht 100% sicher bin. Wenn Sie die tatsächlichen Ansprüche zugreifen müssen aus ClaimsPrincipalmüssen Sie Guss IPrincipalzu ClaimsPrincipal. Dies ist in Ordnung, da wir zu 100% wissen, dass es zur Laufzeit von diesem Typ ist (da dies der Fall HttpContext.Userist). Eigentlich mache ich das einfach gerne im Konstruktor, da ich sicher schon weiß, dass IPrincipal es eine sein wird ClaimsPrincipal.
Wenn Sie sich lustig machen, erstellenClaimsPrincipal Sie einfach ein direktes und übergeben Sie es an alles, was Sie brauchen IPrincipal.
Warum es keine Schnittstelle gibt, weiß IClaimsPrincipalich nicht genau . Ich gehe davon aus, dass MS entschieden hat, dass ClaimsPrincipales sich nur um eine spezialisierte „Sammlung“ handelt, für die keine Schnittstelle erforderlich ist.