2013-02-13 14 views
5

Ich schreibe eine MVC 4 Webanwendung mit benutzerdefinierte Authentifizierung und Autorisierung. Wenn sich ein Benutzer in die Website, ich schaffe enthalten aa FormsAuthenticationTicket und speichern sie in einer CookieMVC Update FormsAuthenticationTicket Benutzerdaten zur Laufzeit

public void SignIn(string userName, bool createPersistentCookie, string UserData) 
{ 
    if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); 

    // Create and tuck away the cookie 
    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddDays(15), createPersistentCookie, UserData); 
    // Encrypt the ticket. 
    string encTicket = FormsAuthentication.Encrypt(authTicket); 

    //// Create the cookie. 
    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket); 
    HttpContext.Current.Response.Cookies.Add(faCookie); 
} 

Die Userdata Saite wird ein Rohrstrang begrenzt und es wird immer mindestens zwei Elemente, BenutzerID | UserRole. Ein Benutzer kann einer oder mehreren Rollen zugewiesen werden. Daher könnten die UserData wie folgt aussehen: UserID | BenutzerRolle | BenutzerRolle | Userrole

ich dann meine eigene benutzerdefinierte generic Haupt haben in Global.asax

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
{ 

     // Get the authentication cookie 
     string cookieName = FormsAuthentication.FormsCookieName; 
     HttpCookie authCookie = Context.Request.Cookies[cookieName]; 

     // If the cookie can't be found, don't issue the ticket 
     if (authCookie == null) return; 

     // Get the authentication ticket and rebuild the principal 
     // & identity 
     FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); 

     string[] UserData = authTicket.UserData.Split(new Char[] { '|' }); 

     GenericIdentity userIdentity = new GenericIdentity(authTicket.Name); 
     GenericPrincipal userPrincipal = new GenericPrincipal(userIdentity, UserData); 
     Context.User = userPrincipal; 
} 

Das alles funktioniert gut, aber in meiner Anwendung, wenn ein Benutzer mehrere Rollen hat, wenn sie sich anmelden, Ich muss ihre Rollen auflisten und sie dann nur eine Rolle auswählen lassen, um basierend auf der ausgewählten Rolle Funktionen auszuführen.

Ich dachte, dies zu tun, vielleicht könnte ich die Rolle übergibt der Benutzer auf ein Verfahren auswählt, erhalten ihre FormsAuthenticationTicket und aktualisieren Sie die Userdata die Rolle, die sie gewählt haben zu reflektieren. -Manager | | Zum Beispiel kann ein Userdata String mit 1 erstellt Antragsteller, dann muss ich beide Rollen auflisten und den Benutzer fragen, welche Rolle sie Funktionalität unter ausführen möchten, wählen Sie sie -Manager und ich dann aktualisieren ihre UserData in ihrem FormsAuthenticationTicket zu 1 | Manager.

Ist das überhaupt möglich, oder gibt es einen besseren Weg?

Jede Hilfe würde sehr geschätzt werden.

Danke an alle.

+0

Das scheint sehr unintuitives Verhalten. Also muss sich der Benutzer abmelden und wieder einloggen, um andere Aktivitäten auszuführen?Es ist besser, den Benutzer nur das tun zu lassen, was er tun darf, und ihn nicht durch die Ringe springen zu lassen. Das ist nur schlechte Usability. –

Antwort

7

Sie könnten immer ändern FormsAuthenticationTicket.

HttpCookie cookie = FormsAuthentication.GetAuthCookie(Username, true); 
var ticket = FormsAuthentication.Decrypt(cookie.Value); 

var newticket = new FormsAuthenticationTicket(ticket.Version, 
               ticket.Name, 
               ticket.IssueDate, 
               ticket.Expiration, 
               true, 
               "new user data", 
               ticket.CookiePath); 

cookie.Value = FormsAuthentication.Encrypt(newticket); 
cookie.Expires = newticket.Expiration.AddHours(24); 
HttpContext.Current.Response.Cookies.Set(cookie); 
1

Wie ich in meinem Kommentar gesagt habe, fühle ich, dass dies sehr schlechte Usability ist. Wenn Sie jedoch entschlossen sind, dies zu tun, dann würde Dzenans Ansatz funktionieren (Sie entfernen im Wesentlichen alle anderen Rollen, nachdem der Benutzer die gewünschte Rolle ausgewählt hat).

Ein anderer Ansatz wäre, ein zusätzliches Feld zu Ihren Benutzerdaten hinzuzufügen, nämlich SelectedRole. Erstellen Sie dann ein benutzerdefiniertes IPrincipal, das dieses Feld enthält. Ein anderer Ansatz wäre, es als Ihren eigenen Cookie zu speichern, obwohl ich sicherstellen würde, dass Sie nicht eine Rolle festlegen, für die der Benutzer nicht autorisiert ist (dh wenn Sie SelectedRole = Admin setzen, stellen Sie sicher, dass Benutzer hat eine Admin-Rolle, bevor Sie ihn verwenden).

+0

Könnten Sie sich bitte diese Frage ansehen? http://stackoverflow.com/questions/24866994/mvc4-custom-authentication-solution vielen Dank! – Timeless