Ich muss etwas ziemlich Einfaches tun: In meiner ASP.NET MVC-Anwendung möchte ich eine benutzerdefinierte IIdentity / IPrincipal festlegen. Was auch immer einfacher / geeigneter ist. Ich möchte die Standardeinstellung erweitern, damit ich so etwas wie User.Identity.Id
und aufrufen kann User.Identity.Role
. Nichts Besonderes, nur ein paar zusätzliche Eigenschaften.
Ich habe Unmengen von Artikeln und Fragen gelesen, aber ich habe das Gefühl, dass ich es schwieriger mache, als es tatsächlich ist. Ich dachte, es wäre einfach. Wenn sich ein Benutzer anmeldet, möchte ich eine benutzerdefinierte IIdentity festlegen. Also dachte ich, ich werde Application_PostAuthenticateRequest
in meiner global.asax implementieren. Dies wird jedoch bei jeder Anforderung aufgerufen, und ich möchte nicht bei jeder Anforderung einen Aufruf an die Datenbank senden, bei dem alle Daten aus der Datenbank angefordert und in ein benutzerdefiniertes IPrincipal-Objekt eingefügt werden. Das scheint auch sehr unnötig, langsam und am falschen Ort zu sein (Datenbankaufrufe dort ausführen), aber ich könnte mich irren. Oder woher sonst würden diese Daten kommen?
Daher dachte ich, wenn sich ein Benutzer anmeldet, kann ich meiner Sitzung einige erforderliche Variablen hinzufügen, die ich der benutzerdefinierten IIdentity im Application_PostAuthenticateRequest
Ereignishandler hinzufüge . Mein Context.Session
ist aber null
da, also ist das auch nicht der richtige Weg.
Ich arbeite jetzt seit einem Tag daran und ich habe das Gefühl, dass mir etwas fehlt. Das sollte nicht zu schwer sein, oder? Ich bin auch ein bisschen verwirrt von all den (halb) verwandten Dingen, die damit einhergehen. MembershipProvider
, MembershipUser
, RoleProvider
, ProfileProvider
, IPrincipal
, IIdentity
, FormsAuthentication
.... Bin ich die einzige, findet das alles sehr verwirrend?
Wenn mir jemand eine einfache, elegante und effiziente Lösung nennen könnte, um einige zusätzliche Daten auf einer IIdentity ohne all den zusätzlichen Flaum zu speichern, wäre das großartig! Ich weiß, dass es ähnliche Fragen zu SO gibt, aber wenn die Antwort, die ich brauche, da drin ist, muss ich sie übersehen haben.
MemberShip...
,Principal
,Identity
. ASP.NET sollte dies einfacher, einfacher und höchstens zwei Ansätze für den Umgang mit der Authentifizierung machen.Antworten:
So mache ich es.
Ich habe mich für IPrincipal anstelle von IIdentity entschieden, da ich nicht sowohl IIdentity als auch IPrincipal implementieren muss.
Erstellen Sie die Schnittstelle
CustomPrincipal
CustomPrincipalSerializeModel - zum Serialisieren benutzerdefinierter Informationen in Benutzerdatenfelder im FormsAuthenticationTicket-Objekt.
Anmeldemethode - Einrichten eines Cookies mit benutzerdefinierten Informationen
Global.asax.cs - Das Lesen von Cookies und das Ersetzen des HttpContext.User-Objekts erfolgt durch Überschreiben von PostAuthenticateRequest
Zugriff in Rasiermesseransichten
und im Code:
Ich denke, der Code ist selbsterklärend. Wenn nicht, lass es mich wissen.
Um den Zugriff noch einfacher zu gestalten, können Sie außerdem einen Basis-Controller erstellen und das zurückgegebene Benutzerobjekt (HttpContext.User) überschreiben:
und dann für jeden Controller:
Damit können Sie auf benutzerdefinierte Felder in Code wie folgt zugreifen:
In Innenansichten funktioniert dies jedoch nicht. Dazu müssten Sie eine benutzerdefinierte WebViewPage-Implementierung erstellen:
Machen Sie es zu einem Standard-Seitentyp in Views / web.config:
und in Ansichten können Sie wie folgt darauf zugreifen:
quelle
Thread.CurrentPrincipal
an dieApplication_PostAuthenticateRequest
für sie arbeiten , wie es lässt sich nicht verlassenHttpContext.Current.User
FormsAuthentication.SignOut();
funktioniert gut für mich.Ich kann nicht direkt für ASP.NET MVC sprechen, aber für ASP.NET Web Forms besteht der Trick darin, ein zu erstellen
FormsAuthenticationTicket
und es in ein Cookie zu verschlüsseln, sobald der Benutzer authentifiziert wurde. Auf diese Weise müssen Sie die Datenbank nur einmal aufrufen (oder AD oder was auch immer Sie zur Durchführung Ihrer Authentifizierung verwenden), und jede nachfolgende Anforderung wird anhand des im Cookie gespeicherten Tickets authentifiziert.Ein guter Artikel dazu:
http://www.ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html(defekter Link)Bearbeiten:
Da der obige Link nicht funktioniert, würde ich die Lösung von LukeP in seiner obigen Antwort empfehlen: https://stackoverflow.com/a/10524305 - Ich würde auch vorschlagen, die akzeptierte Antwort in diese zu ändern.
Bearbeiten 2: Eine Alternative für den defekten Link: https://web.archive.org/web/20120422011422/http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html
quelle
Cache
alsSession
Ersatz zu verwenden, um die Daten auf dem Server zu halten. Kann mir jemand sagen, ob dies ein fehlerhafter Ansatz ist?Hier ist ein Beispiel, um die Arbeit zu erledigen. bool isValid wird durch Betrachten eines Datenspeichers festgelegt (sagen wir Ihre Benutzerdatenbank). UserID ist nur eine ID, die ich pflege. Sie können den Benutzerdaten zusätzliche Informationen wie die E-Mail-Adresse hinzufügen.
Fügen Sie im Golbal Asax den folgenden Code hinzu, um Ihre Informationen abzurufen
Wenn Sie die Informationen später verwenden, können Sie wie folgt auf Ihren benutzerdefinierten Principal zugreifen.
Auf diese Weise können Sie auf benutzerdefinierte Benutzerinformationen zugreifen.
quelle
MVC bietet Ihnen die OnAuthorize-Methode, die von Ihren Controller-Klassen abhängt. Sie können auch einen benutzerdefinierten Aktionsfilter verwenden, um die Autorisierung durchzuführen. MVC macht es ziemlich einfach. Ich habe hier einen Blog-Beitrag dazu gepostet. http://www.bradygaster.com/post/custom-authentication-with-mvc-3.0
quelle
Hier ist eine Lösung, wenn Sie einige Methoden an @User anschließen müssen, um sie in Ihren Ansichten zu verwenden. Keine Lösung für eine ernsthafte Anpassung der Mitgliedschaft, aber wenn die ursprüngliche Frage nur für Ansichten benötigt würde, würde dies möglicherweise ausreichen. Das Folgende wurde zum Überprüfen einer von einem Autorisierungsfilter zurückgegebenen Variablen verwendet, um zu überprüfen, ob einige Links angezeigt werden sollen oder nicht (nicht für irgendeine Art von Autorisierungslogik oder Zugriffsgewährung).
Fügen Sie dann einfach eine Referenz in die Bereiche web.config ein und rufen Sie sie wie unten in der Ansicht auf.
quelle
Basierend auf der Antwort von LukeP , und fügen Sie einige Methoden zum Einrichten
timeout
und zurrequireSSL
Zusammenarbeit hinzuWeb.config
.Die Referenzen Links
Geänderte Codes von LukeP
1, Set
timeout
basierend aufWeb.Config
. Die FormsAuthentication.Timeout erhält den Timeout-Wert, der in web.config definiert ist. Ich habe das Folgende als eine Funktion verpackt, die einticket
Zurück zurückgibt.2, Konfigurieren Sie das Cookie je nach Konfiguration so, dass es sicher ist oder nicht
RequireSSL
.quelle
Also gut, ich bin hier ein ernsthafter Kryptowächter, indem ich diese sehr alte Frage hochziehe, aber es gibt einen viel einfacheren Ansatz, der oben von @Baserz angesprochen wurde. Dies bedeutet, dass eine Kombination aus C # -Erweiterungsmethoden und Caching verwendet wird (Sitzung NICHT verwenden).
Tatsächlich hat Microsoft bereits eine Reihe solcher Erweiterungen im
Microsoft.AspNet.Identity.IdentityExtensions
Namespace bereitgestellt . BeispielsweiseGetUserId()
handelt es sich um eine Erweiterungsmethode, die die Benutzer-ID zurückgibt. Es gibt auchGetUserName()
undFindFirstValue()
, die Ansprüche basierend auf dem IPrincipal zurückgeben.Sie müssen also nur den Namespace einschließen und dann aufrufen
User.Identity.GetUserName()
, um den von ASP.NET Identity konfigurierten Benutzernamen abzurufen.Ich bin nicht sicher, ob dies zwischengespeichert ist, da die ältere ASP.NET-Identität nicht aus offenen Quellen stammt und ich mich nicht darum gekümmert habe, sie zurückzuentwickeln. Wenn dies nicht der Fall ist, können Sie eine eigene Erweiterungsmethode schreiben, die dieses Ergebnis für einen bestimmten Zeitraum zwischenspeichert.
quelle
IsUserAdministrator
oderUserEmail
etc.? Denkst duHttpRuntime.Cache
?Wenn Sie als Ergänzung zum LukeP-Code für Web Forms-Benutzer (nicht MVC) den Zugriff auf den Code hinter Ihren Seiten vereinfachen möchten, fügen Sie einfach den folgenden Code zu einer Basisseite hinzu und leiten Sie die Basisseite auf allen Ihren Seiten ab:
In Ihrem Code dahinter können Sie also einfach auf Folgendes zugreifen:
Was mir in einem Web Form-Szenario fehlt, ist, wie man dasselbe Verhalten in Code erhält, der nicht an die Seite gebunden ist, zum Beispiel in http-Modulen, sollte ich in jeder Klasse immer eine Besetzung hinzufügen, oder gibt es eine intelligentere Möglichkeit, dies zu erreichen?
Vielen Dank für Ihre Antworten und danken LukeP da ich Ihre Beispiele als Basis für meine benutzerdefinierten Benutzer verwendet (was jetzt hat
User.Roles
,User.Tasks
,User.HasPath(int)
,User.Settings.Timeout
und viele andere schöne Dinge)quelle
Ich habe die von LukeP vorgeschlagene Lösung ausprobiert und festgestellt, dass das Authorize-Attribut nicht unterstützt wird. Also habe ich es ein bisschen modifiziert.
Und schließlich in Global.asax.cs
Jetzt kann ich einfach durch Aufrufen auf die Daten in Ansichten und Controllern zugreifen
Um mich abzumelden, rufe ich einfach an
wo AuthManager ist
quelle