Vorgehensweise: Implementieren von IPrincipal

* * *

Auf dieser Seite

Zielsetzung Zielsetzung
Betrifft Betrifft
Verwendung dieses Moduls Verwendung dieses Moduls
Zusammenfassung Zusammenfassung
Benötigte Kenntnisse Benötigte Kenntnisse
Erstellen einer einfachen Webanwendung Erstellen einer einfachen Webanwendung
Konfigurieren der Webanwendung für die Formularauthentifizierung Konfigurieren der Webanwendung für die Formularauthentifizierung
Erzeugen eines Authentifizierungstickets für authentifizierte Benutzer Erzeugen eines Authentifizierungstickets für authentifizierte Benutzer
Erstellen einer Klasse, die IPrincipal implementiert und erweitert Erstellen einer Klasse, die IPrincipal implementiert und erweitert
Erstellen des "CustomPrincipal"-Objekts Erstellen des "CustomPrincipal"-Objekts
Testen der Anwendung Testen der Anwendung
Weitere Ressourcen Weitere Ressourcen

Zielsetzung

Themenbereiche:

  • Erstellen einer Klasse, die die IPrincipal-Schnittstelle implementiert, die in Verbindung mit der rollenbasierten .NET-Sicherheit verwendet werden kann

 

Betrifft

Die Informationen in diesem Modul gelten für folgende Produkte und Technologien:

  • Microsoft Windows® XP oder Windows 2000 Server (mit Service Pack 3) und höhere Betriebssysteme

  • .NET Framework Version 1.0 (mit Service Pack 2) und höhere Versionen

  • Microsoft Visual C#® .NET

 

Verwendung dieses Moduls

Empfehlungen für eine erfolgreiche Arbeit mit diesem Modul:

 

Zusammenfassung

Das Microsoft .NET Framework bietet zwei Implementierungen der IPrincipal-Schnittstelle: WindowsPrincipal und GenericPrincipal. Diese Klassen bieten eine Überprüfungsfunktionalität für die rollenbasierte Autorisierung, die für die meisten Anwendungsszenarios ausreichend ist.

Unter manchen Umständen müssen Sie jedoch eine eigene IPrincipal-Implementierung entwickeln, die benutzerdefinierte Funktionalität bietet. In diesem Modul wird erläutert, wie eine benutzerdefinierte IPrincipal-Klasse implementiert und für die rollenbasierte Autorisierung in einer ASP.NET-Anwendung verwendet wird, die mit der Formularauthentifizierung arbeitet.

 

Benötigte Kenntnisse

Das .NET Framework stellt die Klassen WindowsPrincipal und GenericPrincipal bereit, die grundlegende Rollenüberprüfungsfunktionen für Windows- bzw. Nicht-Windows-Authentifizierungsmechanismen bieten. Mit beiden Klassen wird die IPrincipal-Schnittstelle implementiert. Damit diese Objekte für die Autorisierung verwendet werden können, setzt ASP.NET voraus, dass die Objekte in HttpContext.User gespeichert sind. Bei Windows-basierten Anwendungen müssen sie in Thread.CurrentPrincipal gespeichert sein.

Die von diesen Klassen gebotenen Funktionen sind für die meisten Anwendungsszenarios ausreichend. Anwendungen können die IPrincipal.IsInRole-Methode explizit aufrufen, um programmatische Rollenüberprüfungen durchzuführen. Wird die Demand-Methode der PrincipalPermission-Klasse für die Forderung verwendet, dass ein Aufrufer einer bestimmten Rolle angehören muss (entweder deklarativ oder imperativ), ergibt sich hieraus auch ein Aufruf von IPrincipal.IsInRole.

Unter bestimmten Umständen müssen Sie möglicherweise eigene Prinzipalimplementierungen entwickeln, indem Sie eine Klasse erstellen, die die IPrincipal-Schnittstelle implementiert. Für die .NET-Autorisierung kann jede Klasse verwendet werden, die IPrincipal implementiert.

Zu den Gründen für die Implementierung einer eigenen IPrincipal-Klasse gehören die folgenden:

  • Sie benötigen eine erweiterte Rollenüberprüfungsfunktionalität. Möglicherweise möchten Sie mit Methoden arbeiten, mit denen Sie prüfen können, ob ein bestimmter Benutzer mehreren Rollen angehört. Beispiel:

    
    CustomPrincipal.IsInAllRoles( "Rolle1", "Rolle2", "Rolle3" )
    CustomPrincipal.IsInAnyRole( "Rolle1", "Rolle2", "Rolle3" )
    
  • Sie möchten eine zusätzliche Methode oder Eigenschaft implementieren, die eine Liste der Rollen in Form eines Arrays zurückgibt. Beispiel:

    string[] roles = CustomPrincipal.Roles;
    
  • Sie möchten, dass Ihre Anwendung eine Rollenhierarchielogik durchsetzt. Beispielsweise könnte ein "Senior Manager" als in der Hierarchie höher stehend als ein "Manager" betrachtet werden. Dies könnte mit Methoden wie der folgenden getestet werden:

    
    CustomPrincipal.IsInHigherRole("Manager");
    CustomPrincipal.IsInLowerRole("Manager");
    
  • Sie möchten eine verzögerte Initialisierung der Rollenlisten implementieren. Beispielsweise könnten Sie die Rollenliste nur dann dynamisch laden, wenn eine Rollenüberprüfung angefordert wird.

In diesem Modul wird erläutert, wie eine benutzerdefinierte IPrincipal-Klasse implementiert und für die rollenbasierte Autorisierung in einer ASP.NET-Anwendung verwendet wird, die mit der Formularauthentifizierung arbeitet.

 

Erstellen einer einfachen Webanwendung

Mit diesem Verfahren wird eine neue ASP.NET-Webanwendung erstellt. Die Anwendung enthält zwei Seiten, eine Standardseite, auf die nur authentifizierte Benutzer zugreifen können, und eine Anmeldeseite für die Eingabe der Anmeldeinformationen.

  • So erstellen Sie eine einfache Webanwendung

    1. Starten Sie Visual Studio .NET und erstellen Sie mit C# eine neue ASP.NET-Webanwendung mit Namen CustomPrincipalApp.

    2. Benennen Sie WebForm1.aspx in Logon.aspx um.

    3. Fügen Sie Logon.aspx die in Tabelle 1 aufgeführten Steuerelemente hinzu, um ein Anmeldeformular zu erstellen.

      Tabelle 1: Die Steuerelemente für Logon.aspx

      Typ des Steuerelements Text ID
      Bezeichnungsfeld Benutzername: -
      Bezeichnungsfeld Kennwort -
      Textfeld - txtUserName
      Textfeld - txtPassword
      Schaltfläche Anmelden btnLogon
    4. Legen Sie die TextMode-Eigenschaft des Textfeldsteuerelements txtPassword auf Kennwort fest.

    5. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf CustomPrincipalApp, zeigen Sie auf Hinzufügen und klicken Sie dann auf Web Form hinzufügen.

    6. Geben Sie default.aspx als neuen Namen des Formulars ein und klicken Sie dann auf Öffnen.

 

Konfigurieren der Webanwendung für die Formularauthentifizierung

  • So bearbeiten Sie die Datei Web.config der Anwendung, um die Anwendung für die Formularauthentifizierung zu konfigurieren

    1. Öffnen Sie Web.config im Projektmappen-Explorer.

    2. Suchen Sie das <authentication>-Element und ändern Sie das mode-Attribut in Formulare.

    3. Fügen Sie das folgende <Formulare>-Element als untergeordnetes Element des <authentication>-Elements hinzu und legen Sie die Attribute loginUrl, name, timeout und path wie nachstehend gezeigt fest:

      <authentication mode="Formulare">
        <forms loginUrl="logon.aspx" name="AuthCookie" timeout="60" path="/">
        </forms>
      </authentication>
      
    4. Fügen Sie das folgende <authorization>-Element unterhalb des <authentication>-Elements hinzu. Dies sorgt dafür, dass nur authentifizierte Benutzer auf die Anwendung zugreifen können. Das im Vorfeld eingerichtete loginUrl-Attribut des <authentication>-Elements leitet nicht authentifizierte Anforderungen auf die Seite Logon.aspx um.

      <authorization> 
        <deny users="?" />
        <allow users="*" />
      </authorization>
      

 

Erzeugen eines Authentifizierungstickets für authentifizierte Benutzer

In diesem Verfahren wird der Code zum Erzeugen des Authentifizierungstickets für authentifizierte Benutzer geschrieben. Das Authentifizierungsticket ist eine Art Cookie, das vom FormsAuthenticationModule von ASP.NET verwendet wird.

Der Authentifizierungscode umfasst in der Regel das Nachschlagen des übergebenen Benutzernamens und des Kennworts, und zwar entweder in einer benutzerdefinierten Datenbank oder im Verzeichnisdienst Microsoft Active Directory®.

Weitere Informationen darüber, wie dieses Nachschlagen erfolgt, finden Sie in den folgenden Modulen dieses Handbuches:

  • So erzeugen Sie ein Authentifizierungsticket für authentifizierte Benutzer

    1. Öffnen Sie die Datei Logon.aspx.cs und fügen Sie am Anfang der Datei unterhalb der vorhandenen using-Anweisungen die folgenden using-Anweisungen hinzu:

      using System.Web.Security;
      
    2. Fügen Sie der WebForm1-Klasse die folgende private Hilfsmethode mit Namen IsAuthenticated hinzu, die verwendet wird, um die Benutzernamen und Kennwörter für die Authentifizierung der Benutzer zu überprüfen. In diesem Code wird davon ausgegangen, dass sämtliche Kombinationen aus Benutzernamen und Kennwort gültig sind.

      private bool IsAuthenticated( string username, string password )
      {
        // Suchcode zugunsten größerer Klarheit weggelassen
        // Mit diesem Code werden normalerweise die Kombination aus Benutzernamen und Kennwort
        // anhand einer SQL-Datenbank oder anhand von Active Directory überprüft
        // Authentifizierten Benutzer simulieren
        return true;
      }
      
    3. Fügen Sie die nachstehende private Hilfsmethode mit Namen GetRoles hinzu, die verwendet wird, um die Rollen abzurufen, denen der Benutzer angehört.

      private string GetRoles( string username, string password )
      {
        // Suchcode zugunsten größerer Klarheit weggelassen
        // Mit diesem Code wird normalerweise die Rollenliste aus einer 
        Datenbanktabelle nachgeschlagen.
        // Wenn der Benutzer anhand von Active Directory authentifiziert wurde, 
        // können die Sicherheitsgruppen und/oder Verteilerlisten, zu denen der Benutzer gehört, 
        stattdessen
      verwendet 
        // werden
      
        // Mit dieser GetRoles-Methode wird eine durch einen senkrechten Balken (Pipe) getrennte 
        Zeichenfolge zurückgegeben, die Rollen enthält,
        // und kein Array, da das Format der Zeichenfolge 
        für 
        // die Speicherung als Benutzerdaten im Authentifizierungsticket/Cookie geeignet ist.
        return "Senior Manager|Manager|Mitarbeiter";
      }
      
    4. Zeigen Sie das Formular Logon.aspx im Entwurfsmodus an und doppelklicken Sie dann auf die Schaltfläche Anmelden, um einen Ereignishandler für das Klickereignis zu erstellen.

    5. Fügen Sie einen Aufruf der IsAuthenticated-Methode hinzu und übergeben Sie den Benutzernamen und das Kennwort, der bzw. das im Anmeldeformular eingegeben wurde. Weisen Sie den Rückgabewert einer Variablen vom Typ bool zu, die angibt, ob der Benutzer authentifiziert werden konnte oder nicht.

      bool isAuthenticated = IsAuthenticated( txtUserName.Text, 
                                      txtPassword.Text );
      
    6. Fügen Sie einen Aufruf der GetRoles-Methode hinzu, um für den Fall, dass der Benutzer authentifiziert wird, die Rollenliste des Benutzers abzurufen.

      if (isAuthenticated == true )
      {
        string roles = GetRoles( txtUserName.Text, txtPassword.Text );
      
    7. Erstellen Sie ein neues Formularauthentifizierungsticket, das den Benutzernamen, eine Ablaufzeit und die Liste der Rollen enthält, denen der Benutzer angehört. Beachten Sie, dass die UserData-Eigenschaft des Authentifizierungstickets verwendet wird, um die Rollenliste des Benutzers zu speichern. Beachten Sie zudem, dass mit dem folgenden Code ein nicht persistentes Ticket erstellt wird, obwohl es vom Anwendungsszenario abhängig ist, ob das Ticket/Cookie persistent ist oder nicht.

      
      // Create the authentication ticket
      FormsAuthenticationTicket authTicket = new 
      FormsAuthenticationTicket(1,                          // Version
                               txtUserName.Text,           // Benutzername
                               DateTime.Now,               // Erstellung
                               DateTime.Now.AddMinutes(60),// Ablauf
                               false,                      // Permanent
                               roles );                    // Benutzerdaten
      
    8. Fügen Sie Code zum Erstellen einer verschlüsselten Zeichenfolgendarstellung des Tickets hinzu und speichern Sie diese als Datenwert in einem HttpCookie-Objekt.

      // Verschlüsseln Sie nun das Ticket.
      string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
      // Erstellen Sie ein Cookie, und fügen Sie das verschlüsselte Ticket dem  
      // Cookie in Form von Daten hinzu.
      HttpCookie authCookie = 
                  new HttpCookie(FormsAuthentication.FormsCookieName,
                                  encryptedTicket);
      
    9. Fügen Sie das Cookie der Cookieauflistung hinzu, die an den Browser des Benutzers zurückgegeben wird.

      // Fügen Sie das Cookie der Sammlung ausgehender Cookies hinzu. 
      Response.Cookies.Add(authCookie); 
      
    10. Leiten Sie den Benutzer auf die ursprünglich angeforderte Seite um.

      // Leiten Sie den Benutzer auf die ursprünglich angeforderte Seite um.
       Response.Redirect( FormsAuthentication.GetRedirectUrl(
                                              txtUserName.Text, 
                                              false ));
      }
      

 

Erstellen einer Klasse, die IPrincipal implementiert und erweitert

Mit diesem Verfahren wird eine Klasse erstellt, die die IPrincipal-Schnittstelle implementiert. Darüber hinaus werden der Klasse weitere Methoden und Eigenschaften hinzugefügt, um eine zusätzliche rollenbasierte Autorisierungsfunktionalität bereitzustellen.

  • So erstellen Sie eine Klasse, die IPrincipal implementiert und erweitert

    1. Fügen Sie dem aktuellen Projekt eine neue Klasse mit Namen CustomPrincipal hinzu.

    2. Fügen Sie am Anfang von CustomPrincipal.cs die folgende using-Anweisung hinzu.

      using System.Security.Principal;
      
    3. Leiten Sie die CustomPrincipal-Klasse von der IPrincipal-Schnittstelle ab.

      public class CustomPrincipal : IPrincipal
      
    4. Fügen Sie der Klasse die folgenden Membervariablen vom Typ private hinzu, um das IIdentity-Objekt zu verwalten, das mit dem aktuellen Prinzipal und der Rollenliste des Prinzipals verbunden ist.

      private IIdentity _identity;
      private string [] _roles;
      
    5. Fügen Sie dem Standardkonstruktor der Klasse ein IIdentity-Objekt und ein Array mit Rollen hinzu. Verwenden Sie die übergebenen Werte, um die privaten Membervariablen wie nachstehend gezeigt zu initialisieren.

      public CustomPrincipal(IIdentity identity, string [] roles)
      {
      _identity = identity;
      _roles = new string[roles.Length];
      roles.CopyTo(_roles, 0);
      Array.Sort(_roles);
      }
      
    6. Implementieren Sie die IsInRole-Methode und die Identity-Eigenschaft wie von der IPrincipal-Schnittstelle definiert (siehe unten).

      // IPrincipal Implementation
      public bool IsInRole(string role)
      {
        return Array.BinarySearch( _roles, role ) >= 0 ? true : false;
      }
      public IIdentity Identity
      {
        get
        {
          return _identity;
        }
      }
      
    7. Fügen Sie die beiden folgenden Methoden vom Typ IPrincipal hinzu, mit denen eine erweiterte rollenbasierte Prüfungsfunktion bereitgestellt wird.

      		// Überprüft, ob ein Prinzipal sich in allen Rollen des angegebenen Rollensatzes befindet.
      public bool IsInAllRoles( params string [] roles )
      {
        foreach (string searchrole in roles )
        {
          if (Array.BinarySearch(_roles, searchrole) < 0 )
            return false;
        }
        return true;
      }
      // Überprüft, ob ein Prinzipal sich mindestens einer der Rollen des 
      angegebenen Rollensatzes befindet.
      public bool IsInAnyRoles( params string [] roles )
      {
        foreach (string searchrole in roles )
        {
          if (Array.BinarySearch(_roles, searchrole ) > 0 )
            return true;
        }
        return false;
      }
      

 

Erstellen des "CustomPrincipal"-Objekts

Mit diesem Verfahren wird ein Ereignishandler für die Anwendungsauthentifizierung implementiert: Basierend auf den Informationen im Authentifizierungsticket wird das Objekt CustomPrincipal erstellt, das den authentifizierten Benutzer repräsentiert.

  • So erstellen Sie das "CustomPrincipal"-Objekt

    1. Öffnen Sie im Projektmappen-Explorer die Datei global.asax.

    2. Wechseln Sie in die Codeansicht und fügen Sie am Anfang der Datei die folgenden using-Anweisungen hinzu.

      using System.Web.Security;
      using System.Security.Principal;
      
    3. Suchen Sie den Ereignishandler Application_AuthenticateRequest und fügen Sie den folgenden Code hinzu, um aus der mit der Anforderung übergebenen Cookieauflistung das Formularauthentifizierungscookie abzurufen.

      // Extrahieren Sie das Formularauthentifizierungs-Cookie
      string cookieName = FormsAuthentication.FormsCookieName;
      HttpCookie authCookie = Context.Request.Cookies[cookieName];
      
      if(null == authCookie)
      {
        // Es ist kein Authentfizierungscookie vorhanden.
        return;
      } 
      
    4. Fügen Sie den folgenden Code hinzu, um das Authentifizierungsticket aus dem Formularauthentifizierungscookie zu extrahieren und zu entschlüsseln.

      FormsAuthenticationTicket authTicket = null;
      try
      {
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);
      }
      catch(Exception ex)
      {
        // Protokollieren Sie Ausnahmedetails (aus Gründen der Überschaubarkeit ausgelassen)
        return;
      }
      
      if (null == authTicket)
      {
        // Cookie konnte nicht entschlüsselt werden.
        return; 
      } 
      
    5. Fügen Sie den folgenden Code hinzu, um die per Pipe getrennte Liste der Rollennamen auszulesen, die bei der ursprünglichen Authentifizierung des Benutzers an das Ticket angehängt wurde.

      // Bei der Erstellung des Tickets wurde der UserData-Eigenschaft eine
      // durch einen senkrechten Balken (Pipe) getrennte Zeichenfolge der Rollennamen zugewiesen.
      string[] roles = authTicket.UserData.Split('|');
      
    6. Fügen Sie den folgenden Code hinzu, um das FormsIdentity-Objekt mit dem Benutzernamen zu erstellen, der dem Ticketnamen entnommen wurde, und um ein CustomPrincipal-Objekt zu erstellen, das diese Identität zusammen mit der Rollenliste des Benutzers enthält.

      // Erstellen Sie ein Identitätsobjekt
      FormsIdentity id = new FormsIdentity( authTicket ); 
      
      // Dieser Prinzipal wird über die gesamte Anforderung hinweg übertragen.
      CustomPrincipal principal = new CustomPrincipal(id, roles);
      // Fügen Sie das neue Prinzipalobjekt an das aktuelle HttpContext-Objekt an
      Context.User = principal;
      

 

Testen der Anwendung

Mit diesem Verfahren wird der Seite default.aspx Code hinzugefügt, um Informationen aus dem CustomPrincipal-Objekt anzuzeigen, das an das aktuelle HttpContext-Objekt angefügt wurde. So wird sichergestellt, dass das Objekt ordnungsgemäß erstellt und der aktuellen Webanforderung zugewiesen wurde. Hiermit wird zudem die rollenbasierte Funktionalität geprüft, die von der neuen Klasse unterstützt wird.

  • So testen Sie die Anwendung

    1. Doppelklicken Sie im Projektmappen-Explorer auf default.aspx.

    2. Doppelklicken Sie auf das Webformular default.aspx, um den Ereignishandler zum Laden der Seite anzuzeigen.

    3. Führen Sie einen Bildlauf zum Anfang der Datei durch und fügen Sie unterhalb der vorhandenen using-Anweisungen die folgende using-Anweisung hinzu.

      using System.Security.Principal;
      
    4. Kehren Sie zum Ereignishandler für das Laden der Seite zurück und fügen Sie den folgenden Code hinzu, um den Identitätsnamen anzuzeigen, der dem CustomPrincipal-Objekt zugewiesen wurde, das mit der aktuellen Webanforderung zusammenhängt.

      CustomPrincipal cp = HttpContext.Current.User as CustomPrincipal;
      Response.Write( "Authentifizierte Identität: " +  
                      cp.Identity.Name );
      Response.Write( "<p>" );
      
    5. Fügen Sie den folgenden Code hinzu, um die Rollenmitgliedschaft der aktuell authentifizierten Identität zu prüfen, und zwar unter Verwendung der standardmäßigen IsInRole-Methode und der zusätzlich von der CustomPrincipal-Klasse unterstützten Methoden IsInAnyRole und IsInAllRoles.

      if ( cp.IsInRole("Senior Manager") )
      {
        Response.Write( cp.Identity.Name + " Befindet sich in der " + "Rolle
        "Senior Manager"" );
        Response.Write( "<p>" );            
      }
      
        if ( cp.IsInAnyRoles("Senior Manager", "Manager", "Mitarbeiter", "
        Verkauf") )
        {
          Response.Write( cp.Identity.Name + " befindet sich in einer der angegebenen 
          Rollen");
          Response.Write( "<p>" );
        }
        if ( cp.IsInAllRoles("Senior Manager", "Manager", "Mitarbeiter", "
        Verkauf") )
        {
          Response.Write( cp.Identity.Name + " befindet sich in ALLEN der angegebenen 
          Rollen" );
          Response.Write( "<p>" );
        }
        else
        {
          Response.Write( cp.Identity.Name + 
                          " befindet sich nicht in ALLEN der angegebenen Rollen" );
          Response.Write("<p>");
        }
      
        if ( cp.IsInRole("Verkauf") )
          Response.Write( "Benutzer befindet sich in der Rolle "Verkauf"<p>" );
        else
          Response.Write( "Benutzer befindet sich nicht in der Rolle "Verkauf"<p>" );
      
    6. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf default.aspx und dann auf Als Startseite festlegen.

    7. Klicken Sie im Menü Erstellen auf Projektmappe erstellen.

    8. Drücken Sie Strg+F5, um die Anwendung auszuführen. Da default.aspx als Startseite konfiguriert ist, ist dies auch die zuerst angeforderte Seite.

    9. Wenn Sie auf die Anmeldeseite umgeleitet werden (da Sie anfänglich ja nicht über ein Authentifizierungsticket verfügen), geben Sie irgendeinen Benutzernamen und ein beliebiges Kennwort ein, und klicken Sie dann auf Anmelden.

    10. Vergewissern Sie sich, dass Sie auf die Seite default.aspx umgeleitet werden und dass die Benutzeridentität und die korrekten Rollendetails angezeigt werden. Der Benutzer ist ein Mitglied der Rollen Senior Manager, Manager und Mitarbeiter, jedoch kein Mitglied der Rolle Verkauf.

 

Weitere Ressourcen

Weitere Informationen zur formularbasierten Authentifizierung finden Sie in den folgenden Modulen dieses Handbuches: