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 IPrincipal
wie 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 User
direkt 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 IPrincipal
undIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipal
und IIdentity
reprä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.User
oder ControllerBase.HttpContext.User
Sie bekommen ein Objekt , das eine sein , garantiert ClaimsPrincipal
Objekt , 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 IPrincipal
und definitiv nicht IHttpContextAccessor
.
Wichtig: Verschwenden Sie keine Zeit damit, IPrincipal
direkt in Ihren Controller oder Ihre Aktionsmethode zu injizieren - dies ist sinnlos, da User
es 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, IPrincipal
um 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 ClaimsPrincipal
müssen Sie Guss IPrincipal
zu ClaimsPrincipal
. Dies ist in Ordnung, da wir zu 100% wissen, dass es zur Laufzeit von diesem Typ ist (da dies der Fall HttpContext.User
ist). 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ß IClaimsPrincipal
ich nicht genau . Ich gehe davon aus, dass MS entschieden hat, dass ClaimsPrincipal
es sich nur um eine spezialisierte „Sammlung“ handelt, für die keine Schnittstelle erforderlich ist.