Kolumne: Dino talks

Benutzerdefinierte Prinzipalobjekte in ASP.NET MVC
Kommentare

In ASP.NET wird die Identität eines authentifizierten Benutzers mit dem von HttpContext verfügbar gemachten User-Objekt dargestellt. Das User-Objekt hat den Typ IPrincipal, und IPrincipal ist in .NET der Vertrag für den Sicherheitskontext des Benutzers, in dessen Namen der Code ausgeführt wird. In ASP.NET gibt es mehrere unterschiedliche IPrincipal-Objekte, die zusätzliche Informationen verfügbar machen, beispielsweise über die Rollen eines bestimmten Benutzers. Doch wie sieht es aus, wenn Sie einen benutzerdefinierten Prinzipal brauchen? In diesem Artikel erfahren Sie, was erforderlich ist, um ein benutzerdefiniertes Prinzipalobjekt innerhalb der Grenzen einer ASP.NET-MVC-Anwendung zu erstellen. Die meisten Konzepte lassen sich allerdings auch direkt auf ASP.NET-Webformulare übertragen.

Authentifizierung ist der Prozess, durch den die Identität des Benutzers verifiziert wird. Wenn der Authentifizierungsprozess erfolgreich endet, speichert die Anwendung Benutzerinformationen in einem Identity-Objekt. Normalerweise kapselt das Identity-Objekt den Namen des Benutzers. Der Prinzipal ist ein Objekt, das den Sicherheitskontext der Anwendung darstellt. Ein Principal-Objekt kapselt Identitätsinformationen und optional die Rollen, die der Benutzer im Kontext der Anwendung spielt.

Die User-Eigenschaft des HttpContext-Objekts ist vom Typ IPrincipal. Diese Schnittstelle verkörpert den öffentlichen Vertrag, den alle Principal-Objekte erfüllen müssen. Meistens ist RolePrincipal der eigentliche Typ hinter User. Genau das ist der Fall, wenn die Rollenverwaltung auf der Anwendungsebene aktiviert wird. Die Klasse RolePrincipal ist sicherlich nützlich, erweist sich aber für die meisten Anwendungen als recht generisch. In praktischen Szenarien ist es oftmals erforderlich, dem Sicherheitskontext einige benutzerdefinierte Informationen hinzuzufügen, damit man wesentlich mehr als nur den Namen und Rollen über den Benutzer wissen kann, nachdem er authentifiziert wurde. Diesmal zeige ich Ihnen, wie Sie den Authentifizierungsvorgang anpassen, um ein benutzerdefiniertes Cookie zu erzeugen, und wie Sie dann diese Informationen abrufen und in einem benutzerdefinierten Prinzipalobjekt verpacken. Ich werde alle Techniken im Kontext einer ASP.NET-MVC-Anwendung vorstellen, wobei sich die gleichen Verfahren aber auch auf Webformulare anwenden lassen. Ehrlich gesagt habe ich zuerst gelernt, wie man das Ganze in Webformularen realisiert, und erst dann habe ich diese Erkenntnisse auf ASP.NET MVC übertragen.

Cookies und Authentifizierungstickets

Wenn Sie eine Beispiel-ASP.NET-MVC-Anwendung mit Visual Studio erstellen, haben Sie eine FormsAuthenticationService-Klasse. (Standardmäßig ist diese Klasse in der Datei AccountModels.cs untergebracht.) Diesen Code sollten Sie aus der Klasse in eine eigene Klasse – vorzugsweise in eine separate Assembly nur für Dienste – verschieben (Listing 1).

Listing 1: Implementierung der Authentifizierungsklasse
public class FormsAuthenticationService : 
             IFormsAuthenticationService
{
    public void SignIn(
       string userName, bool createPersistentCookie) 
    {
        if (String.IsNullOrEmpty(userName)) 
           throw new ArgumentException();

        FormsAuthentication.SetAuthCookie(
              userName, createPersistentCookie); 
    }

    public void SignOut()
    {
        FormsAuthentication.SignOut();
    }
}  

Das Authentifizierungsticket wird durch die Methode SetAuthCookie erstellt. Die Methode packt Benutzerinformationen in einen Ticketcontainer, verschlüsselt das Ticket und speichert es in einem HTTP-Cookie. Schließlich wird das Cookie an die Antwort angefügt. Der Ticketcontainer wird durch die Klasse FormsAuthenticationTicket dargestellt. Ziemlich eigenartig ist es, dass die Ticketklasse eine UserData-Eigenschaft bereitstellt, die speziell hinzugefügt wurde, um Entwicklern zu ermöglichen, ihre eigenen anwendungsspezifischen Daten im Ticket und anschließend innerhalb des Authentifizierungscookies zu speichern. Allerdings ist es nicht ohne Weiteres möglich, auf die UserData-Eigenschaft zuzugreifen, um benutzerdefinierte Daten in den Authentifizierungsvorgang einzubringen. Es wäre großartig, wenn die Methode SetAuthCookie ein drittes Argument speziell für die Benutzerdaten bereitstellen würde. Trotzdem können Sie ein benutzerdefiniertes Ticket erstellen. Allerdings muss dazu die Logik von SetAuthCookie etwas „umgebogen“ werden. Und das geht wie folgt.

Ein benutzerdefiniertes Authentifizierungsticket erstellen

In ASP.NET MVC ändern Sie zunächst den Quellcode der Methode SignIn in der Klasse FormsAuthenticationService. Diese Klasse wird durch die Visual-Studio-Vorlage definiert und gehört keineswegs zum Framework. Somit können Sie bei Bedarf ihren Prototyp nach Belieben ändern. In der modifizierten Version von SignIn erstellen Sie zuerst ein benutzerdefiniertes Authentifizierungsticket, das benutzerdefinierte Daten enthält. Als Nächstes verschlüsseln Sie es und speichern es in einem zweckmäßig konfigurierten Cookie. Dann hängen Sie das Cookie einfach an das Response-Objekt an (Listing 2).

Listing 2: Erstellen eines benutzerdefinierten Authentifizierungstickets
public void SignIn(String userName, 
                 Boolean createPersistentCookie) 
{
  // Grab user information to insert
  var registryService = new RegistryService();
  var appUser = registryService.GetUser(userName); 
  var customInfo = String.Format("{0}|{1}", 
           appUser.PictureName, appUser.Balance);  

  // Create and encrypt the ticket
  var ticket = new FormsAuthenticationTicket(
      2,                             // Version number
      userName,                      // Username
      DateTime.Now,                  // Issue date
      DateTime.Now.AddMinutes(30),   // Expiration date
      createPersistentCookie,        // Is it persistent? 
      customInfo                     // User data
  ); 
  var encTicket = FormsAuthentication.Encrypt(ticket); 

  // Store the ticket into a cookie
  var cookie = FormsAuthentication.GetAuthCookie(
                      FormsAuthentication.FormsCookieName, 
                      createPersistentCookie); 
  cookie.Value = encTicket; 

  // Append the cookie to the response
  HttpContext.Current.Response.Cookies.Add(cookie); 
}  

Das letzte Argument des FormsAuthenticationTicket-Konstruktors ist ein Zeichenfolgenwert, der die UserData-Eigenschaft des Tickets füllt. Es liegt in Ihrer eigenen Verantwortlichkeit, benutzerdefinierte Daten in ein Zeichenfolgenformat zu serialisieren, das Sie später parsen können. Es empfiehlt sich, mit GetAuthCookie ein vorbereitetes Cookie abzurufen, das nach den Einstellungen in der Datei web.config konfiguriert ist. Dann müssen Sie lediglich den Cookie-Wert durch das verschlüsselte Ticket ersetzen.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -