Freigeben über


Rollenbasierte Autorisierung (C#)

von Scott Mitchell

Hinweis

Seit diesem Artikel wurden die ASP.NET-Mitgliedschaftsanbieter von ASP.NET Identity abgelöst. Es wird dringend empfohlen, Apps so zu aktualisieren, dass sie die ASP.NET Identity-Plattform anstelle der Mitgliedschaftsanbieter verwenden, die zum Zeitpunkt des Schreibens dieses Artikels vorgestellt wurden. ASP.NET Identity bietet eine Reihe von Vorteilen gegenüber dem ASP.NET Mitgliedschaftssystem, darunter:

  • Bessere Leistung
  • Verbesserte Erweiterbarkeit und Testbarkeit
  • Unterstützung für OAuth, OpenID Connect und zweistufige Authentifizierung
  • Unterstützung der anspruchsbasierten Identität
  • Bessere Interoperabilität mit ASP.Net Core

Code herunterladen oder PDF herunterladen

Dieses Tutorial beginnt mit einem Blick darauf, wie das Rollenframework die Rollen eines Benutzers mit seinem Sicherheitskontext verknüpft. Anschließend wird untersucht, wie rollenbasierte URL-Autorisierungsregeln angewendet werden. Anschließend untersuchen wir die Verwendung deklarativer und programmgesteuerter Mittel zum Ändern der angezeigten Daten und der Von einer ASP.NET Seite angebotenen Funktionalität.

Einführung

Im Tutorial " Benutzerbasierte Autorisierung" haben wir erfahren, wie sie mithilfe der URL-Autorisierung angeben, welche Benutzer eine bestimmte Gruppe von Seiten besuchen können. Mit nur ein wenig Markup in Web.configkönnten wir ASP.NET anweisen, nur authentifizierten Benutzern zu erlauben, eine Seite zu besuchen. Oder wir könnten diktieren, dass nur Benutzer Tito und Bob zugelassen wurden, oder dass alle authentifizierten Benutzer mit Ausnahme von Sam zugelassen wurden.

Neben der URL-Autorisierung haben wir uns auch mit deklarativen und programmgesteuerten Techniken zur Steuerung der angezeigten Daten und der Von einer Seite angebotenen Funktionalität basierend auf dem Besuch des Benutzers befasst. Insbesondere haben wir eine Seite erstellt, auf der der Inhalt des aktuellen Verzeichnisses aufgeführt ist. Jeder konnte diese Seite besuchen, aber nur authentifizierte Benutzer konnten den Inhalt der Dateien anzeigen, und nur Tito konnte die Dateien löschen.

Das Anwenden von Autorisierungsregeln auf Benutzerbasis kann zu einem Buchführungs alptraum werden. Ein wartungsfreundlicherer Ansatz ist die verwendung der rollenbasierten Autorisierung. Die gute Nachricht ist, dass die uns zur Verfügung stehenden Tools für die Anwendung von Autorisierungsregeln mit Rollen genauso gut funktionieren wie für Benutzerkonten. URL-Autorisierungsregeln können Rollen anstelle von Benutzern angeben. Das LoginView-Steuerelement, das unterschiedliche Ausgaben für authentifizierte und anonyme Benutzer rendert, kann so konfiguriert werden, dass unterschiedliche Inhalte basierend auf den Rollen des angemeldeten Benutzers angezeigt werden. Und die Rollen-API enthält Methoden zum Bestimmen der Rollen des angemeldeten Benutzers.

Dieses Tutorial beginnt mit einem Blick darauf, wie das Rollenframework die Rollen eines Benutzers mit seinem Sicherheitskontext verknüpft. Anschließend wird untersucht, wie rollenbasierte URL-Autorisierungsregeln angewendet werden. Anschließend untersuchen wir die Verwendung deklarativer und programmgesteuerter Mittel zum Ändern der angezeigten Daten und der Von einer ASP.NET Seite angebotenen Funktionalität. Jetzt geht‘s los!

Grundlegendes zur Zuordnung von Rollen zum Sicherheitskontext eines Benutzers

Wenn eine Anforderung in die ASP.NET-Pipeline eintritt, ist sie einem Sicherheitskontext zugeordnet, der Informationen enthält, die den Anforderer identifizieren. Bei Verwendung der Formularauthentifizierung wird ein Authentifizierungsticket als Identitätstoken verwendet. Wie im Tutorial Eine Übersicht über die Formularauthentifizierung erläutert, ist der FormsAuthenticationModule für die Ermittlung der Identität des Anforderers verantwortlich, was während des AuthenticateRequest Ereignisses geschieht.

Wenn ein gültiges, nicht abgelaufenes Authentifizierungsticket gefunden wird, decodiert es, FormsAuthenticationModule um die Identität des Anforderers zu ermitteln. Es erstellt ein neues GenericPrincipal Objekt und weist dieses dem HttpContext.User Objekt zu. Der Zweck eines Prinzipals wie GenericPrincipal, besteht darin, den Namen des authentifizierten Benutzers und die Rollen zu identifizieren, zu denen er gehört. Dieser Zweck wird dadurch deutlich, dass alle Prinzipalobjekte über eine Identity -Eigenschaft und eine IsInRole(roleName) -Methode verfügen. Der FormsAuthenticationModuleist jedoch nicht an der Aufzeichnung von Rolleninformationen interessiert, und das objekt, das GenericPrincipal er erstellt, gibt keine Rollen an.

Wenn das Rollenframework aktiviert ist, tritt das RoleManagerModule HTTP-Modul nach dem FormsAuthenticationModule ein und identifiziert die Rollen des authentifizierten Benutzers während des PostAuthenticateRequest Ereignisses, das nach dem AuthenticateRequest Ereignis ausgelöst wird. Wenn die Anforderung von einem authentifizierten Benutzer stammt, überschreibt der RoleManagerModule das GenericPrincipal von FormsAuthenticationModule erstellte Objekt und ersetzt es durch ein RolePrincipal -Objekt. Die RolePrincipal -Klasse verwendet die Rollen-API, um zu bestimmen, zu welchen Rollen der Benutzer gehört.

Abbildung 1 zeigt den ASP.NET Pipelineworkflows bei Verwendung der Formularauthentifizierung und des Rollenframeworks. Der FormsAuthenticationModule führt zuerst aus, identifiziert den Benutzer über sein Authentifizierungsticket und erstellt ein neues GenericPrincipal Objekt. Als Nächstes werden die RoleManagerModule Schritte in und das Objekt mit einem RolePrincipal -Objekt überschriebenGenericPrincipal.

Wenn ein anonymer Benutzer die Website besucht, erstellt weder das FormsAuthenticationModule noch RoleManagerModule ein Prinzipalobjekt.

Die ASP.NET Pipelineereignisse für einen authentifizierten Benutzer bei Verwendung der Formularauthentifizierung und des Rollenframeworks

Abbildung 1: Die ASP.NET Pipelineereignisse für einen authentifizierten Benutzer bei Verwendung der Formularauthentifizierung und des Rollenframeworks (Hier klicken, um ein vollständiges Bild anzuzeigen)

Die RolePrincipal -Methode des IsInRole(roleName) Objekts ruft auf Roles.GetRolesForUser , um die Rollen für den Benutzer abzurufen, um zu bestimmen, ob der Benutzer mitglied von roleName ist. Bei Verwendung von führt dies SqlRoleProviderzu einer Abfrage für die Rollenspeicherdatenbank. Bei Verwendung rollenbasierter URL-Autorisierungsregeln wird die Methode der RolePrincipal's IsInRole bei jeder Anforderung an eine Seite aufgerufen, die durch die rollenbasierten URL-Autorisierungsregeln geschützt ist. Anstatt die Rolleninformationen in der Datenbank bei jeder Anforderung suchen zu müssen, enthält das Rollenframework eine Option zum Zwischenspeichern der Rollen des Benutzers in einem Cookie.

Wenn das Rollenframework so konfiguriert ist, dass die Rollen des Benutzers in einem Cookie zwischengespeichert werden, RoleManagerModule wird das Cookie während des EreignissesEndRequest der ASP.NET Pipeline erstellt. Dieses Cookie wird in nachfolgenden Anforderungen in der PostAuthenticateRequestverwendet, wobei das RolePrincipal Objekt erstellt wird. Wenn das Cookie gültig ist und nicht abgelaufen ist, werden die Daten im Cookie analysiert und verwendet, um die Rollen des Benutzers aufzufüllen. Dadurch wird gespeichert, dass die RolePrincipal Klasse nicht aufgerufen werden muss, um die Roles Rollen des Benutzers zu bestimmen. Abbildung 2 zeigt diesen Workflow.

Die Rolleninformationen des Benutzers können in einem Cookie gespeichert werden, um die Leistung zu verbessern.

Abbildung 2: Die Rolleninformationen des Benutzers können in einem Cookie gespeichert werden, um die Leistung zu verbessern (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Standardmäßig ist der Rollencache-Cookiemechanismus deaktiviert. Sie kann über das <roleManager> Konfigurationsmarkup in Web.configaktiviert werden. Im Tutorial Erstellen und Verwalten von Rollen wurde die Verwendung des <roleManager> -Elements zum Angeben von Rollenanbietern erläutert. Daher sollten Sie dieses Element bereits in der Datei Ihrer Anwendung Web.config enthalten. Die Einstellungen für Rollencachecookies werden als Attribute des <roleManager> Elements angegeben und in Tabelle 1 zusammengefasst.

Hinweis

Die in Tabelle 1 aufgeführten Konfigurationseinstellungen geben die Eigenschaften des resultierenden Rollencachecookies an. Weitere Informationen zu Cookies, ihrer Funktionsweise und ihren verschiedenen Eigenschaften finden Sie in diesem Tutorial zu Cookies.

Eigenschaft Beschreibung
cacheRolesInCookie Ein boolescher Wert, der angibt, ob die Zwischenspeicherung von Cookies verwendet wird. Der Standardwert lautet false.
cookieName Der Name des Rollencachecookies. Der Standardwert ist ". ASPXROLES".
cookiePath Der Pfad für das Rollennamenscooky. Das path-Attribut ermöglicht es einem Entwickler, den Bereich eines Cookies auf eine bestimmte Verzeichnishierarchie zu beschränken. Der Standardwert ist "/", der den Browser informiert, das Authentifizierungsticket-Cookie an jede Anforderung an die Domäne zu senden.
cookieProtection Gibt an, welche Techniken zum Schutz des Rollencachecookies verwendet werden. Die zulässigen Werte sind: All (Standardwert); Encryption; Noneund Validation.
cookieRequireSSL Ein boolescher Wert, der angibt, ob eine SSL-Verbindung zum Übertragen des Authentifizierungscookies erforderlich ist. Standardwert: false.
cookieSlidingExpiration Ein boolescher Wert, der angibt, ob das Timeout des Cookies jedes Mal zurückgesetzt wird, wenn der Benutzer die Website während einer einzelnen Sitzung besucht. Standardwert: false. Dieser Wert ist nur relevant, wenn createPersistentCookie auf truefestgelegt ist.
cookieTimeout Gibt die Zeit in Minuten an, nach der das Cookie für das Authentifizierungsticket abläuft. Standardwert: 30. Dieser Wert ist nur relevant, wenn createPersistentCookie auf truefestgelegt ist.
createPersistentCookie Ein boolescher Wert, der angibt, ob das Rollencachecooky ein Sitzungscookies oder ein persistentes Cookie ist. Wenn false (standard) wird ein Sitzungscooky verwendet, das gelöscht wird, wenn der Browser geschlossen wird. Wenn trueein persistentes Cookie verwendet wird, läuft cookieTimeout es je nach Wert von cookieSlidingExpirationMinuten ab, nachdem es erstellt wurde oder nach dem vorherigen Besuch.
domain Gibt den Domänenwert des Cookies an. Der Standardwert ist eine leere Zeichenfolge, die dazu führt, dass der Browser die Domäne verwendet, von der er ausgestellt wurde (z. B. www.yourdomain.com). In diesem Fall wird das Cookie nicht gesendet, wenn Anforderungen an Unterdomänen wie z. B. admin.yourdomain.com. Wenn das Cookie an alle Unterdomänen übergeben werden soll, müssen Sie das domain Attribut anpassen und auf "yourdomain.com" festlegen.
maxCachedResults Gibt die maximale Anzahl von Rollennamen an, die im Cookie zwischengespeichert werden. Der Standard ist 25. Erstellt RoleManagerModule kein Cookie für Benutzer, die mehr als maxCachedResults Rollen angehören. Folglich verwendet die RolePrincipal -Methode des IsInRole Objekts die Roles -Klasse, um die Rollen des Benutzers zu bestimmen. Der Grund maxCachedResults besteht darin, dass viele Benutzer-Agents cookies nicht zulassen, die größer als 4.096 Bytes sind. Diese Obergrenze soll also die Wahrscheinlichkeit einer Überschreitung dieser Größenbeschränkung verringern. Wenn Sie extrem lange Rollennamen haben, sollten Sie einen kleineren maxCachedResults Wert angeben. Wenn Sie extrem kurze Rollennamen haben, können Sie diesen Wert wahrscheinlich erhöhen.

Tabelle 1: Konfigurationsoptionen für Rollencachecookies

Konfigurieren wir unsere Anwendung so, dass nicht persistente Rollencachecookies verwendet werden. Aktualisieren Sie dazu das <roleManager> Element in Web.config , um die folgenden cookiebezogenen Attribute einzuschließen:

<roleManager enabled="true"    
          defaultProvider="SecurityTutorialsSqlRoleProvider"    
          cacheRolesInCookie="true"    
          createPersistentCookie="false"    
          cookieProtection="All">    

     <providers>    
     ...    
     </providers>    
</roleManager>

Ich habe das <roleManager> -Element aktualisiert, indem ich drei Attribute hinzugefügt habe: cacheRolesInCookie, createPersistentCookieund cookieProtection. Wenn Sie auf truefestlegencacheRolesInCookie, RoleManagerModule werden die Rollen des Benutzers jetzt automatisch in einem Cookie zwischengespeichert, anstatt die Rolleninformationen des Benutzers bei jeder Anforderung suchen zu müssen. Ich setz die createPersistentCookie Attribute und cookieProtection explizit auf false bzw All. . Technisch gesehen musste ich keine Werte für diese Attribute angeben, da ich sie nur ihren Standardwerten zugewiesen habe, aber ich habe sie hier eingefügt, um deutlich zu machen, dass ich keine permanenten Cookies verwende und dass das Cookie sowohl verschlüsselt als auch überprüft ist.

Das war es schon! Fortan speichert das Rollenframework die Rollen der Benutzer in Cookies zwischen. Wenn der Browser des Benutzers keine Cookies unterstützt oder seine Cookies gelöscht oder verloren gehen, ist dies irgendwie keine große Sache – das RolePrincipal Objekt verwendet einfach die Roles -Klasse, falls kein Cookie (oder ein ungültiges oder abgelaufenes) verfügbar ist.

Hinweis

Die Microsoft-Gruppe Patterns & Practices rät von der Verwendung persistenter Rollencache-Cookies ab. Da der Besitz des Rollencachecookies ausreicht, um die Rollenmitgliedschaft nachzuweisen, kann ein Hacker, wenn er irgendwie Zugriff auf das Cookie eines gültigen Benutzers erhalten kann, die Identität dieses Benutzers annehmen. Die Wahrscheinlichkeit, dass dies geschieht, steigt, wenn das Cookie im Browser des Benutzers gespeichert wird. Weitere Informationen zu dieser Sicherheitsempfehlung sowie zu anderen Sicherheitsbedenken finden Sie in der Sicherheitsfrageliste für ASP.NET 2.0.

Schritt 1: Definieren von Role-Based URL-Autorisierungsregeln

Wie im Tutorial zur benutzerbasierten Autorisierung erläutert, bietet die URL-Autorisierung eine Möglichkeit, den Zugriff auf eine Reihe von Seiten auf Benutzer- oder Rollenbasis einzuschränken. Die URL-Autorisierungsregeln werden in Web.config der Verwendung des <authorization> Elements mit <allow> und <deny> untergeordneten Elementen geschrieben. Zusätzlich zu den benutzerbezogenen Autorisierungsregeln, die in den vorherigen Tutorials erläutert wurden, kann jedes <allow> untergeordnete <deny> Element auch Folgendes enthalten:

  • Eine bestimmte Rolle
  • Eine durch Trennzeichen getrennte Liste von Rollen

Beispielsweise gewähren die URL-Autorisierungsregeln diesen Benutzern in den Rollen Administratoren und Vorgesetzte Zugriff, verweigern jedoch allen anderen Zugriff:

<authorization>
     <allow roles="Administrators, Supervisors" />
     <deny users="*" />
</authorization>

Das <allow> Element im obigen Markup gibt an, dass die Rollen "Administratoren" und "Supervisors" zulässig sind. Das <deny> -Element weist an, dass alle Benutzer verweigert werden.

Konfigurieren wir unsere Anwendung so, dass die ManageRoles.aspxSeiten , UsersAndRoles.aspxund CreateUserWizardWithRoles.aspx nur für die Benutzer in der Rolle "Administratoren" zugänglich sind, während die RoleBasedAuthorization.aspx Seite für alle Besucher zugänglich bleibt.

Um dies zu erreichen, beginnen Sie, indem Sie dem Roles Ordner eine Web.config Datei hinzufügen.

Hinzufügen einer Web.config datei zum Verzeichnis

Abbildung 3: Hinzufügen einer Web.config Datei zum Roles Verzeichnis (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Fügen Sie als Nächstes das folgende Konfigurationsmarkup zu hinzu Web.config:

<?xml version="1.0"?>    

<configuration>    
     <system.web>    
          <authorization>    
               <allow roles="Administrators" />    
               <deny users="*"/>    
          </authorization>    

     </system.web>

     <!-- Allow all users to visit RoleBasedAuthorization.aspx -->    
     <location path="RoleBasedAuthorization.aspx">    
          <system.web>    
               <authorization>    
                    <allow users="*" />    

               </authorization>    
          </system.web>    
     </location>    
</configuration>

Das <authorization> -Element im <system.web> Abschnitt gibt an, dass nur Benutzer mit der Rolle "Administratoren" auf die ASP.NET Ressourcen im Roles Verzeichnis zugreifen können. Das <location> -Element definiert einen alternativen Satz von URL-Autorisierungsregeln für die RoleBasedAuthorization.aspx Seite, sodass alle Benutzer die Seite besuchen können.

Nachdem Sie Ihre Änderungen in gespeichert haben Web.config, melden Sie sich als Benutzer an, der nicht in der Rolle "Administratoren" ist, und versuchen Sie dann, eine der geschützten Seiten zu besuchen. Die UrlAuthorizationModule erkennt, dass Sie nicht berechtigt sind, die angeforderte Ressource zu besuchen. FormsAuthenticationModule Folglich werden Sie zur Anmeldeseite weitergeleitet. Die Anmeldeseite leitet Sie dann zur UnauthorizedAccess.aspx Seite weiter (siehe Abbildung 4). Diese letzte Umleitung von der Anmeldeseite zu UnauthorizedAccess.aspx erfolgt aufgrund von Code, den wir der Anmeldeseite in Schritt 2 des Tutorials zur benutzerbasierten Autorisierung hinzugefügt haben. Insbesondere leitet die Anmeldeseite jeden authentifizierten Benutzer automatisch zu UnauthorizedAccess.aspx um, wenn die Abfragezeichenfolge einen ReturnUrl Parameter enthält, da dieser Parameter angibt, dass der Benutzer auf der Anmeldeseite angekommen ist, nachdem er versucht hat, eine Seite anzuzeigen, für die er nicht autorisiert war.

Nur Benutzer mit der Administratorrolle können die geschützten Seiten anzeigen.

Abbildung 4: Nur Benutzer in der Administratorrolle können die geschützten Seiten anzeigen (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Melden Sie sich ab, und melden Sie sich dann als Benutzer an, der der Rolle "Administratoren" angehört. Jetzt sollten Sie die drei geschützten Seiten anzeigen können.

Tito kann die Seite

Abbildung 5: Tito kann die UsersAndRoles.aspx Seite besuchen, da er sich in der Rolle "Administratoren" befindet (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Hinweis

Bei der Angabe von URL-Autorisierungsregeln – für Rollen oder Benutzer – ist es wichtig zu beachten, dass die Regeln einzeln und von oben nach unten analysiert werden. Sobald eine Übereinstimmung gefunden wird, wird dem Benutzer der Zugriff gewährt oder verweigert, je nachdem, ob die Übereinstimmung in einem - oder <deny> -<allow>Element gefunden wurde. Wenn keine Übereinstimmung gefunden wird, erhält der Benutzer Zugriff. Wenn Sie den Zugriff auf ein oder mehrere Benutzerkonten einschränken möchten, müssen Sie daher unbedingt ein <deny> -Element als letztes Element in der URL-Autorisierungskonfiguration verwenden. Wenn Ihre URL-Autorisierungsregeln keine<deny>-Element wird allen Benutzern Zugriff gewährt. Eine ausführlichere Diskussion darüber, wie die URL-Autorisierungsregeln analysiert werden, finden Sie im Tutorial zur benutzerbasierten Autorisierung im Abschnitt "A Look on How the UrlAuthorizationModule Uses the Authorization Rules to Grant or Deny Access".

Schritt 2: Einschränken der Funktionalität basierend auf den Rollen des aktuell angemeldeten Benutzers

Die URL-Autorisierung erleichtert das Angeben grober Autorisierungsregeln, die angeben, welche Identitäten zulässig sind und denen die Anzeige einer bestimmten Seite (oder aller Seiten in einem Ordner und seinen Unterordnern) verweigert wird. In bestimmten Fällen möchten wir es jedoch allen Benutzern ermöglichen, eine Seite zu besuchen, aber die Funktionalität der Seite basierend auf den Rollen des besuchenden Benutzers einzuschränken. Dies kann das Anzeigen oder Ausblenden von Daten basierend auf der Rolle des Benutzers oder das Anbieten zusätzlicher Funktionen für Benutzer umfassen, die einer bestimmten Rolle angehören.

Solche differenzierten rollenbasierten Autorisierungsregeln können entweder deklarativ oder programmgesteuert (oder durch eine Kombination aus beiden) implementiert werden. Im nächsten Abschnitt erfahren Sie, wie Sie die deklarative Feinkornautorisierung über das LoginView-Steuerelement implementieren. Danach werden wir programmgesteuerte Techniken untersuchen. Bevor wir uns jedoch mit der Anwendung feinkörniger Autorisierungsregeln befassen können, müssen wir zunächst eine Seite erstellen, deren Funktionalität von der Rolle des Benutzers abhängt, der sie besucht.

Erstellen Wir nun eine Seite, auf der alle Benutzerkonten im System in einer GridView aufgelistet sind. Die GridView enthält den Benutzernamen, die E-Mail-Adresse, das Datum der letzten Anmeldung und Kommentare zum Benutzer. Zusätzlich zur Anzeige der Benutzerinformationen enthält gridView Bearbeitungs- und Löschfunktionen. Wir erstellen zunächst diese Seite mit der Bearbeitungs- und Löschfunktion, die allen Benutzern zur Verfügung steht. In den Abschnitten "Using the LoginView Control" und "Programmatically Limiting Functionality" (Verwenden des LoginView-Steuerelements) und "Programmgesteuertes Einschränken der Funktionalität" erfahren Sie, wie Sie diese Features basierend auf der Rolle des Gastbenutzers aktivieren oder deaktivieren.

Hinweis

Die ASP.NET Seite, die wir erstellen möchten, verwendet ein GridView-Steuerelement, um die Benutzerkonten anzuzeigen. Da sich diese Tutorialreihe auf Formularauthentifizierung, Autorisierung, Benutzerkonten und Rollen konzentriert, möchte ich nicht zu viel Zeit damit verbringen, die inneren Funktionsweisen des GridView-Steuerelements zu diskutieren. Dieses Tutorial enthält zwar spezifische schrittweise Anweisungen zum Einrichten dieser Seite, aber es befasst sich nicht mit den Details, warum bestimmte Entscheidungen getroffen wurden oder welche Auswirkungen bestimmte Eigenschaften auf die gerenderte Ausgabe haben. Eine gründliche Untersuchung des GridView-Steuerelements finden Sie in der Tutorialreihe Arbeiten mit Daten in ASP.NET 2.0 .

Öffnen Sie zunächst die RoleBasedAuthorization.aspx Seite im Roles Ordner. Ziehen Sie ein GridView-Objekt von der Seite auf die Designer, und legen Sie es ID auf festUserGrid. In einem Moment schreiben wir Code, der die Membership.GetAllUsers -Methode aufruft und das resultierende MembershipUserCollection Objekt an gridView bindet. enthält MembershipUserCollection ein MembershipUser -Objekt für jedes Benutzerkonto im System. MembershipUser Objekte verfügen über Eigenschaften wie UserName, Email, LastLoginDateusw.

Bevor wir den Code schreiben, der die Benutzerkonten an das Raster bindet, definieren wir zunächst die GridView-Felder. Klicken Sie im Smarttag von GridView auf den Link "Spalten bearbeiten", um das Dialogfeld Felder zu starten (siehe Abbildung 6). Deaktivieren Sie hier das Kontrollkästchen "Felder automatisch generieren" in der unteren linken Ecke. Da diese GridView Bearbeitungs- und Löschfunktionen enthalten soll, fügen Sie ein CommandField hinzu, und legen Sie dessen ShowEditButton Eigenschaften und ShowDeleteButton auf True fest. Fügen Sie als Nächstes vier Felder zum Anzeigen der UserNameEigenschaften , Email, LastLoginDateund Comment hinzu. Verwenden Sie ein BoundField für die beiden schreibgeschützten Eigenschaften (UserName und ) und LastLoginDateTemplateFields für die beiden bearbeitbaren Felder (Email und Comment).

Lassen Sie das erste BoundField die -Eigenschaft anzeigen; legen Sie die UserNameHeaderText Eigenschaften und DataField auf "UserName" fest. Dieses Feld kann nicht bearbeitet werden, daher legen Sie seine ReadOnly Eigenschaft auf True fest. Konfigurieren Sie das LastLoginDate BoundField, indem Sie auf HeaderText "Last Login" und its DataField auf "LastLoginDate" festlegen. Formatieren Sie die Ausgabe dieses BoundField so, dass nur das Datum (anstelle von Datum und Uhrzeit) angezeigt wird. Um dies zu erreichen, legen Sie die Eigenschaft dieser BoundField-Eigenschaft HtmlEncode auf False und die zugehörige DataFormatString Eigenschaft auf "{0:d}" fest. Legen Sie außerdem die ReadOnly -Eigenschaft auf True fest.

Legen Sie die HeaderText Eigenschaften der beiden TemplateFields auf "Email" und "Comment" fest.

Die Felder der GridView können über das Dialogfeld Felder konfiguriert werden.

Abbildung 6: Die Felder von GridView können über das Dialogfeld Felder konfiguriert werden (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Jetzt müssen und EditItemTemplate für die ItemTemplate TemplateFields "Email" und "Comment" definiert werden. Fügen Sie jedem der ItemTemplate Eigenschaften ein Label Web-Steuerelement hinzu, und binden Sie deren Text Eigenschaften an die Email Eigenschaften bzw Comment . an.

Fügen Sie für das TemplateField "Email" ein TextBox-Element mit dem Namen Email hinzuEditItemTemplate, und binden Sie die Text -Eigenschaft mithilfe der bidirektionalen Datenbindung an die Email -Eigenschaft. Fügen Sie requiredFieldValidator und RegularExpressionValidator hinzu, EditItemTemplate um sicherzustellen, dass ein Besucher, der die eigenschaft Email bearbeitet, eine gültige E-Mail-Adresse eingegeben hat. Fügen Sie für das TemplateField "Comment" ein mehrzeiliges TextBox-Element mit dem Namen Comment hinzu EditItemTemplate. Legen Sie die Eigenschaften und Rows von Columns TextBox auf 40 bzw. 4 fest, und binden Sie dann die Text -Eigenschaft mithilfe der bidirektionalen Datenbindung an die Comment -Eigenschaft.

Nach dem Konfigurieren dieser TemplateFields sollte ihr deklaratives Markup wie folgt aussehen:

<asp:TemplateField HeaderText="Email">    
     <ItemTemplate>    
          <asp:Label runat="server" ID="Label1" Text='<%# Eval("Email") %>'></asp:Label>    

     </ItemTemplate>    
     <EditItemTemplate>    
          <asp:TextBox runat="server" ID="Email" Text='<%# Bind("Email") %>'></asp:TextBox>    

          <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"    
               ControlToValidate="Email" Display="Dynamic"    
               ErrorMessage="You must provide an email address." 
               SetFocusOnError="True">*</asp:RequiredFieldValidator>    

          <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"    
               ControlToValidate="Email" Display="Dynamic"    
               ErrorMessage="The email address you have entered is not valid. Please fix 
               this and try again."    
               SetFocusOnError="True"    

               ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">*
          </asp:RegularExpressionValidator>    
     </EditItemTemplate>    
</asp:TemplateField>

<asp:TemplateField HeaderText="Comment">    
     <ItemTemplate>    
          <asp:Label runat="server" ID="Label2" Text='<%# Eval("Comment") %>'></asp:Label>    

     </ItemTemplate>    
     <EditItemTemplate>    
          <asp:TextBox runat="server" ID="Comment" TextMode="MultiLine"
               Columns="40" Rows="4" Text='<%# Bind("Comment") %>'>

          </asp:TextBox>    
     </EditItemTemplate>    
</asp:TemplateField>

Beim Bearbeiten oder Löschen eines Benutzerkontos müssen wir den Eigenschaftswert dieses UserName Benutzers kennen. Legen Sie die Eigenschaft von DataKeyNames GridView auf "UserName" fest, damit diese Informationen über die GridView-Sammlung DataKeys verfügbar sind.

Fügen Sie schließlich der Seite ein ValidationSummary-Steuerelement hinzu, und legen Sie dessen ShowMessageBox Eigenschaft auf True und seine ShowSummary Eigenschaft auf False fest. Mit diesen Einstellungen zeigt ValidationSummary eine clientseitige Warnung an, wenn der Benutzer versucht, ein Benutzerkonto mit einer fehlenden oder ungültigen E-Mail-Adresse zu bearbeiten.

<asp:ValidationSummary ID="ValidationSummary1"
               runat="server"
               ShowMessageBox="True"
               ShowSummary="False" />

Wir haben nun das deklarative Markup dieser Seite abgeschlossen. Unsere nächste Aufgabe besteht darin, den Satz von Benutzerkonten an gridView zu binden. Fügen Sie eine Methode namens BindUserGrid der CodeBehind-Klasse der RoleBasedAuthorization.aspx Seite hinzu, die die MembershipUserCollection von zurückgegebene an Membership.GetAllUsers gridView UserGrid bindet. Rufen Sie diese Methode über den Page_Load Ereignishandler beim ersten Seitenbesuch auf.

protected void Page_Load(object sender, EventArgs e)    
{    
     if (!Page.IsPostBack)    
          BindUserGrid();    
}

private void BindUserGrid()    
{    
     MembershipUserCollection allUsers = Membership.GetAllUsers();    
     UserGrid.DataSource = allUsers;    
     UserGrid.DataBind();    
}

Wenn dieser Code vorhanden ist, besuchen Sie die Seite über einen Browser. Wie abbildung 7 zeigt, sollten Sie eine GridView-Auflistungsinformationen zu jedem Benutzerkonto im System sehen.

UserGrid GridView listet Informationen zu jedem Benutzer im System auf.

Abbildung 7: GridView UserGrid listet Informationen zu jedem Benutzer im System auf (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Hinweis

GridView UserGrid listet alle Benutzer in einer nicht ausgelagerten Benutzeroberfläche auf. Diese einfache Rasterschnittstelle eignet sich nicht für Szenarien, in denen mehrere Dutzend oder mehr Benutzer vorhanden sind. Eine Möglichkeit besteht darin, GridView so zu konfigurieren, dass paging aktiviert wird. Die Membership.GetAllUsers -Methode verfügt über zwei Überladungen: eine, die keine Eingabeparameter akzeptiert und alle Benutzer zurückgibt, und eine, die ganzzahlige Werte für den Seitenindex und die Seitengröße akzeptiert und nur die angegebene Teilmenge der Benutzer zurückgibt. Die zweite Überladung kann verwendet werden, um die Benutzer effizienter zu durchlaufen, da sie nur die genaue Teilmenge der Benutzerkonten und nicht alle von ihnen zurückgibt. Wenn Sie über Tausende von Benutzerkonten verfügen, sollten Sie eine filterbasierte Schnittstelle in Betracht ziehen, die nur Benutzer anzeigt, deren UserName mit einem ausgewählten Zeichen beginnt, für instance. Eignet Membership.FindUsersByName method sich ideal zum Erstellen einer filterbasierten Benutzeroberfläche. Das Erstellen einer solchen Schnittstelle wird in einem zukünftigen Tutorial erläutert.

Das GridView-Steuerelement bietet integrierte Bearbeitungs- und Löschunterstützung, wenn das Steuerelement an ein ordnungsgemäß konfiguriertes Datenquellensteuerelement wie SqlDataSource oder ObjectDataSource gebunden ist. Die UserGrid Daten des GridView-Steuerelements sind jedoch programmgesteuert gebunden. Daher müssen wir Code schreiben, um diese beiden Aufgaben auszuführen. Insbesondere müssen Ereignishandler für die Ereignisse , RowCancelingEdit, RowUpdatingund von GridView RowEditingerstellt werden, die RowDeleting ausgelöst werden, wenn ein Besucher auf die Schaltflächen Bearbeiten, Abbrechen, Aktualisieren oder Löschen in GridView klickt.

Erstellen Sie zunächst die Ereignishandler für die Ereignisse , RowCancelingEditund RowUpdating von RowEditingGridView, und fügen Sie dann den folgenden Code hinzu:

protected void UserGrid_RowEditing(object sender, GridViewEditEventArgs e)
{
     // Set the grid's EditIndex and rebind the data

     UserGrid.EditIndex = e.NewEditIndex;
     BindUserGrid();
}

protected void UserGrid_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

protected void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     // Exit if the page is not valid
     if (!Page.IsValid)
          return;

     // Determine the username of the user we are editing
     string UserName = UserGrid.DataKeys[e.RowIndex].Value.ToString();

     // Read in the entered information and update the user
     TextBox EmailTextBox = UserGrid.Rows[e.RowIndex].FindControl("Email") as TextBox;
     TextBox CommentTextBox = UserGrid.Rows[e.RowIndex].FindControl("Comment") as TextBox;

     // Return information about the user
     MembershipUser UserInfo = Membership.GetUser(UserName);

     // Update the User account information
     UserInfo.Email = EmailTextBox.Text.Trim();
     UserInfo.Comment = CommentTextBox.Text.Trim();

     Membership.UpdateUser(UserInfo);

     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

Die RowEditing Ereignishandler und RowCancelingEdit legen einfach die Eigenschaft von EditIndex GridView fest und binden dann die Liste der Benutzerkonten erneut an das Raster. Die interessanten Dinge passieren im RowUpdating Ereignishandler. Dieser Ereignishandler stellt zunächst sicher, dass die Daten gültig sind, und greift dann den UserName Wert des bearbeiteten Benutzerkontos aus der DataKeys Sammlung ab. Anschließend Email wird programmgesteuert auf die TextBoxen und Comment in den beiden TemplateFields EditItemTemplate verwiesen. Ihre Text Eigenschaften enthalten die bearbeitete E-Mail-Adresse und den Kommentar.

Um ein Benutzerkonto über die Mitgliedschafts-API zu aktualisieren, müssen wir zuerst die Benutzerinformationen abrufen, was wir über einen Aufruf von Membership.GetUser(userName)tun. Die Eigenschaften und Comment des Email zurückgegebenen MembershipUser Objekts werden dann mit den Werten aktualisiert, die von der Bearbeitungsoberfläche in die beiden TextBoxes eingegeben wurden. Schließlich werden diese Änderungen mit einem Aufruf von Membership.UpdateUsergespeichert. Der RowUpdating Ereignishandler wird abgeschlossen, indem gridView auf seine Vorbearbeitungsschnittstelle zurückgesetzt wird.

Erstellen Sie als Nächstes den RowDeleting Ereignishandler, und fügen Sie dann den folgenden Code hinzu:

protected void UserGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
     // Determine the username of the user we are editing
     string UserName = UserGrid.DataKeys[e.RowIndex].Value.ToString();

     // Delete the user
     Membership.DeleteUser(UserName);

     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

Der obige Ereignishandler beginnt mit dem Abrufen des UserName Werts aus der GridView-AuflistungDataKeys. Dieser UserName Wert wird dann an die Methode der Membership-Klasse DeleteUserübergeben. Die DeleteUser -Methode löscht das Benutzerkonto aus dem System, einschließlich zugehöriger Mitgliedschaftsdaten (z. B. zu welchen Rollen dieser Benutzer gehört). Nach dem Löschen des Benutzers wird das Raster auf -1 festgelegt (falls der Benutzer auf Löschen geklickt hat, während sich eine andere Zeile im Bearbeitungsmodus EditIndex befand), und die BindUserGrid -Methode wird aufgerufen.

Hinweis

Die Schaltfläche Löschen erfordert keine Bestätigung durch den Benutzer, bevor das Benutzerkonto gelöscht wird. Ich ermutige Sie, eine Form der Benutzerbestätigung hinzuzufügen, um die Wahrscheinlichkeit zu mindern, dass ein Konto versehentlich gelöscht wird. Eine der einfachsten Möglichkeiten, eine Aktion zu bestätigen, ist ein clientseitiges Bestätigungsdialogfeld. Weitere Informationen zu diesem Verfahren finden Sie unter Hinzufügen Client-Side Bestätigung beim Löschen.

Stellen Sie sicher, dass diese Seite wie erwartet funktioniert. Sie sollten in der Lage sein, die E-Mail-Adresse und kommentare eines Benutzers zu bearbeiten und jedes Benutzerkonto zu löschen. Da die RoleBasedAuthorization.aspx Seite für alle Benutzer zugänglich ist, kann jeder Benutzer – auch anonyme Besucher – diese Seite besuchen und Benutzerkonten bearbeiten und löschen! Lassen Sie uns diese Seite aktualisieren, sodass nur Benutzer in den Rollen Supervisors und Administratoren die E-Mail-Adresse und kommentare eines Benutzers bearbeiten können und nur Administratoren ein Benutzerkonto löschen können.

Im Abschnitt "Verwenden des LoginView-Steuerelements" wird die Verwendung des LoginView-Steuerelements erläutert, um spezifische Anweisungen für die Rolle des Benutzers anzuzeigen. Wenn eine Person mit der Rolle "Administratoren" diese Seite besucht, zeigen wir Anweisungen zum Bearbeiten und Löschen von Benutzern an. Wenn ein Benutzer mit der Rolle "Supervisors" diese Seite erreicht, werden Anweisungen zum Bearbeiten von Benutzern angezeigt. Und wenn der Besucher anonym ist oder nicht in der Rolle "Supervisors" oder "Administratoren" tätig ist, wird eine Meldung angezeigt, in der erklärt wird, dass er Benutzerkontoinformationen nicht bearbeiten oder löschen kann. Im Abschnitt "Programmgesteuerte Einschränkung der Funktionalität" schreiben wir Code, der die Schaltflächen Bearbeiten und Löschen basierend auf der Rolle des Benutzers programmgesteuert ein- oder ausblendet.

Verwenden des LoginView-Steuerelements

Wie wir in früheren Tutorials gesehen haben, ist das LoginView-Steuerelement nützlich, um verschiedene Schnittstellen für authentifizierte und anonyme Benutzer anzuzeigen, aber das LoginView-Steuerelement kann auch verwendet werden, um unterschiedliche Markups basierend auf den Rollen des Benutzers anzuzeigen. Wir verwenden ein LoginView-Steuerelement, um je nach Rolle des besuchenden Benutzers verschiedene Anweisungen anzuzeigen.

Fügen Sie zunächst eine LoginView oberhalb von UserGrid GridView hinzu. Wie bereits erwähnt, verfügt das LoginView-Steuerelement über zwei integrierte Vorlagen: AnonymousTemplate und LoggedInTemplate. Geben Sie in beiden Vorlagen eine kurze Meldung ein, die den Benutzer darüber informiert, dass er keine Benutzerinformationen bearbeiten oder löschen kann.

<asp:LoginView ID="LoginView1" runat="server">
     <LoggedInTemplate>
          You are not a member of the Supervisors or Administrators roles. Therefore you
          cannot edit or delete any user information.
     </LoggedInTemplate>
     <AnonymousTemplate>
          You are not logged into the system. Therefore you cannot edit or delete any user

          information.
     </AnonymousTemplate>
</asp:LoginView>

Zusätzlich zu AnonymousTemplate und LoggedInTemplatekann das LoginView-Steuerelement Rollengruppen enthalten, bei denen es sich um rollenspezifische Vorlagen handelt. Jede RoleGroup enthält eine einzelne Eigenschaft, , die angibt, Rolesauf welche Rollen die RoleGroup angewendet wird. Die Roles Eigenschaft kann auf eine einzelne Rolle (z. B. "Administratoren") oder auf eine durch Trennzeichen getrennte Liste von Rollen (z. B. "Administratoren, Vorgesetzte") festgelegt werden.

Klicken Sie zum Verwalten der Rollengruppen im Smarttag des Steuerelements auf den Link "Rollengruppen bearbeiten", um den Rollengruppensammlungs-Editor anzuzeigen. Fügen Sie zwei neue RoleGroups hinzu. Legen Sie die erste RoleGroup-Eigenschaft Roles auf "Administratoren" und die zweite auf "Supervisors" fest.

Verwalten der Role-Specific-Vorlagen von LoginView über den RoleGroup-Sammlungs-Editor

Abbildung 8: Verwalten der Role-Specific-Vorlagen von LoginView über den RoleGroup-Sammlungs-Editor (Klicken Sie hier, um ein Bild in voller Größe anzuzeigen)

Klicken Sie auf OK, um den RoleGroup-Sammlungs-Editor zu schließen. Dadurch wird das deklarative Markup von LoginView so aktualisiert, dass ein <RoleGroups> Abschnitt mit einem <asp:RoleGroup> untergeordneten Element für jede Im RoleGroup-Auflistungs-Editor definierte RoleGroup enthalten ist. Darüber hinaus enthält die Dropdownliste "Ansichten" im Smarttag von LoginView, in dem zunächst nur und AnonymousTemplateLoggedInTemplate aufgeführt waren, nun auch die hinzugefügten RoleGroups.

Bearbeiten Sie die Rollengruppen, sodass Benutzern in der Rolle "Supervisors" Anweisungen zum Bearbeiten von Benutzerkonten angezeigt werden, während Benutzern in der Rolle "Administratoren" Anweisungen zum Bearbeiten und Löschen angezeigt werden. Nachdem Sie diese Änderungen vorgenommen haben, sollte das deklarative Markup Ihres LoginView-Steuerelements in etwa wie folgt aussehen.

<asp:LoginView ID="LoginView1" runat="server">
     <RoleGroups>
          <asp:RoleGroup Roles="Administrators">
               <ContentTemplate>
                    As an Administrator, you may edit and delete user accounts. 
                    Remember: With great power comes great responsibility!

               </ContentTemplate>
          </asp:RoleGroup>
          <asp:RoleGroup Roles="Supervisors">
               <ContentTemplate>
                    As a Supervisor, you may edit users&#39; Email and Comment information. 
                    Simply click the Edit button, make your changes, and then click Update.
               </ContentTemplate>
          </asp:RoleGroup>
     </RoleGroups>

     <LoggedInTemplate>
          You are not a member of the Supervisors or Administrators roles. 
          Therefore you cannot edit or delete any user information.
     </LoggedInTemplate>
     <AnonymousTemplate>
          You are not logged into the system. Therefore you cannot edit or delete any user
          information.
     </AnonymousTemplate>
</asp:LoginView>

Nachdem Sie diese Änderungen vorgenommen haben, speichern Sie die Seite, und besuchen Sie sie dann über einen Browser. Besuchen Sie zuerst die Seite als anonymer Benutzer. Ihnen sollte die Meldung angezeigt werden: "Sie sind nicht beim System angemeldet. Daher können Sie keine Benutzerinformationen bearbeiten oder löschen." Melden Sie sich dann als authentifizierter Benutzer an, der sich jedoch weder in der Rolle "Supervisors" noch "Administratoren" befindet. Dieses Mal sollte die Meldung "Sie sind kein Mitglied der Rollen "Supervisors" oder "Administrators" angezeigt werden. Daher können Sie keine Benutzerinformationen bearbeiten oder löschen."

Melden Sie sich als Nächstes als Benutzer an, der Mitglied der Rolle "Supervisors" ist. Dieses Mal sollte die rollenspezifische Meldung Supervisors angezeigt werden (siehe Abbildung 9). Wenn Sie sich als Benutzer mit der Rolle "Administratoren" anmelden, sollte die rollenspezifische Meldung "Administratoren" angezeigt werden (siehe Abbildung 10).

Bruce wird den Supervisors Role-Specific Nachricht angezeigt.

Abbildung 9: Bruce wird die Meldung "Supervisors Role-Specific" angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Tito wird die Nachricht

Abbildung 10: Tito wird die Meldung "Administratoren Role-Specific" angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wie die Screenshots in Den Abbildungen 9 und 10 zeigen, rendert LoginView nur eine Vorlage, auch wenn mehrere Vorlagen angewendet werden. Bruce und Tito sind beide angemeldete Benutzer, aber LoginView rendert nur die übereinstimmende RoleGroup und nicht die LoggedInTemplate. Darüber hinaus gehört Tito sowohl zu den Rollen Administratoren als auch Supervisors, aber das LoginView-Steuerelement rendert die rollespezifische Vorlage "Administratoren" anstelle der Vorgesetzten.

Abbildung 11 veranschaulicht den Workflow, der vom LoginView-Steuerelement verwendet wird, um zu bestimmen, welche Vorlage gerendert werden soll. Beachten Sie, dass, wenn mehr als eine RoleGroup angegeben ist, die LoginView-Vorlage die erste RoleGroup rendert, die übereinstimmt. Anders ausgedrückt: Wenn wir die Supervisors RoleGroup als erste Rollengruppe und die Administratoren als zweite platziert hätten, dann würde Tito beim Besuch dieser Seite die Meldung Supervisors sehen.

Der Workflow des LoginView-Steuerelements zum Bestimmen der zu rendernden Vorlage

Abbildung 11: Workflow des LoginView-Steuerelements zum Bestimmen der zu rendernden Vorlage (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Programmgesteuerte Einschränkung der Funktionalität

Während das LoginView-Steuerelement verschiedene Anweisungen basierend auf der Rolle des Benutzers anzeigt, der die Seite besucht, bleiben die Schaltflächen Bearbeiten und Abbrechen für alle sichtbar. Wir müssen die Schaltflächen Bearbeiten und Löschen für anonyme Besucher und Benutzer, die weder die Rolle "Supervisors" noch "Administratoren" haben, programmgesteuert ausblenden. Wir müssen die Schaltfläche Löschen für alle Personen ausblenden, die kein Administrator sind. Um dies zu erreichen, schreiben wir ein wenig Code, der programmgesteuert auf die Edit and Delete LinkButtons von CommandField verweist und deren Visible Eigenschaften bei Bedarf auf falsefestlegt.

Die einfachste Möglichkeit, programmgesteuert auf Steuerelemente in einem CommandField zu verweisen, besteht darin, sie zuerst in eine Vorlage zu konvertieren. Klicken Sie dazu im Smarttag von GridView auf den Link "Spalten bearbeiten", wählen Sie in der Liste der aktuellen Felder das CommandField aus, und klicken Sie auf den Link "Dieses Feld in ein Vorlagenfeld konvertieren". Dadurch wird das CommandField mit und EditItemTemplatein ein ItemTemplate TemplateField umgewandelt. ItemTemplate enthält die LinkButtons bearbeiten und löschen, während die EditItemTemplate LinkButtons Aktualisieren und Abbrechen enthalten.

Konvertieren des CommandField in ein TemplateField

Abbildung 12: Konvertieren des Befehlsfelds in ein TemplateField (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Aktualisieren Sie die LinkButtons bearbeiten und löschen in , ItemTemplateund legen Sie deren ID Eigenschaften auf Werte von EditButton bzw DeleteButton. fest.

<asp:TemplateField ShowHeader="False">
     <EditItemTemplate>
          <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True"
               CommandName="Update" Text="Update"></asp:LinkButton>

           <asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False"
                CommandName="Cancel" Text="Cancel"></asp:LinkButton>

     </EditItemTemplate>
     <ItemTemplate>
          <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False"
               CommandName="Edit" Text="Edit"></asp:LinkButton>

           <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
               CommandName="Delete" Text="Delete"></asp:LinkButton>

     </ItemTemplate>
</asp:TemplateField>

Wenn Daten an gridView gebunden sind, listet GridView die Datensätze in seiner DataSource -Eigenschaft auf und generiert ein entsprechendes GridViewRow -Objekt. Wenn jedes GridViewRow Objekt erstellt wird, wird das RowCreated -Ereignis ausgelöst. Um die Schaltflächen Bearbeiten und Löschen für nicht autorisierte Benutzer auszublenden, müssen wir einen Ereignishandler für dieses Ereignis erstellen und programmgesteuert auf die LinkButtons Bearbeiten und Löschen verweisen und deren Visible Eigenschaften entsprechend festlegen.

Erstellen Sie einen Ereignishandler für das RowCreated Ereignis, und fügen Sie dann den folgenden Code hinzu:

protected void UserGrid_RowCreated(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.DataRow && e.Row.RowIndex != UserGrid.EditIndex)
     {
          // Programmatically reference the Edit and Delete LinkButtons
          LinkButton EditButton = e.Row.FindControl("EditButton") as LinkButton;

          LinkButton DeleteButton = e.Row.FindControl("DeleteButton") as LinkButton;

          EditButton.Visible = (User.IsInRole("Administrators") || User.IsInRole("Supervisors"));
          DeleteButton.Visible = User.IsInRole("Administrators");
     }
}

Beachten Sie, dass das RowCreated Ereignis für alle GridView-Zeilen ausgelöst wird, einschließlich Kopfzeile, Fußzeile, Pagerschnittstelle usw. Wir möchten nur programmgesteuert auf die LinkButtons Bearbeiten und Löschen verweisen, wenn es sich um eine Datenzeile handelt, die sich nicht im Bearbeitungsmodus befindet (da die Zeile im Bearbeitungsmodus die Schaltflächen Aktualisieren und Abbrechen anstelle von Bearbeiten und Löschen aufweist). Diese Überprüfung wird von der if -Anweisung behandelt.

Wenn es sich um eine Datenzeile handelt, die sich nicht im Bearbeitungsmodus befindet, wird auf die LinkButtons Edit und Delete verwiesen, und ihre Visible Eigenschaften werden basierend auf den booleschen Werten festgelegt, die von der -Methode des UserIsInRole(roleName) Objekts zurückgegeben werden. Das User-Objekt verweist auf den Prinzipal, der RoleManagerModulevon erstellt wurde. Daher verwendet die IsInRole(roleName) -Methode die Rollen-API, um zu bestimmen, ob der aktuelle Besucher zu roleName gehört.

Hinweis

Wir hätten die Roles-Klasse direkt verwenden können und den Aufruf von User.IsInRole(roleName) durch einen Aufruf der Roles.IsUserInRole(roleName) -Methode ersetzen können. Ich habe mich für die Verwendung der Methode des Prinzipalobjekts IsInRole(roleName) in diesem Beispiel entschieden, da sie effizienter ist als die direkte Verwendung der Rollen-API. Weiter oben in diesem Tutorial haben wir den Rollen-Manager so konfiguriert, dass er die Rollen des Benutzers in einem Cookie zwischenspeichert. Diese zwischengespeicherten Cookiedaten werden nur verwendet, wenn die Methode des IsInRole(roleName) Prinzipals aufgerufen wird. Direkte Aufrufe der Rollen-API beinhalten immer eine Fahrt zum Rollenspeicher. Auch wenn Rollen nicht in einem Cookie zwischengespeichert werden, ist das Aufrufen der Methode des Prinzipalobjekts IsInRole(roleName) in der Regel effizienter, da die Ergebnisse beim ersten Aufruf während einer Anforderung zwischengespeichert werden. Die Rollen-API hingegen führt keine Zwischenspeicherung aus. Da das RowCreated Ereignis einmal für jede Zeile in GridView ausgelöst wird, umfasst die Verwendung User.IsInRole(roleName) nur einen Trip zum Rollenspeicher, während Roles.IsUserInRole(roleName)N-Fahrten erforderlich sind, wobei N die Anzahl der im Raster angezeigten Benutzerkonten darstellt.

Die Eigenschaft der Visible Schaltfläche Bearbeiten wird auf true festgelegt, wenn der Benutzer, der diese Seite besucht, die Rolle "Administratoren" oder "Supervisors" hat. Andernfalls wird sie auf falsefestgelegt. Die Eigenschaft der Visible Schaltfläche Löschen ist nur auf true festgelegt, wenn der Benutzer in der Rolle "Administratoren" ist.

Testen Sie diese Seite über einen Browser. Wenn Sie die Seite als anonymer Besucher oder als Benutzer besuchen, der weder ein Supervisor noch ein Administrator ist, ist das CommandField leer. Es ist weiterhin vorhanden, aber als dünner Streifen ohne die Schaltflächen Bearbeiten oder Löschen.

Hinweis

Es ist möglich, das CommandField vollständig auszublenden, wenn ein Nicht-Supervisor und ein Nicht-Administrator die Seite besucht. Ich belasse dies als Übung für den Leser.

Die Schaltflächen

Abbildung 13: Die Schaltflächen Bearbeiten und Löschen sind für Nicht-Vorgesetzte und Nichtadministratoren ausgeblendet (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wenn ein Benutzer, der der Rolle "Supervisors" (aber nicht der Rolle "Administratoren") angehört, besucht, wird ihm nur die Schaltfläche Bearbeiten angezeigt.

Während die Schaltfläche Bearbeiten für Supervisors verfügbar ist, ist die Schaltfläche

Abbildung 14: Während die Schaltfläche Bearbeiten für Vorgesetzte verfügbar ist, ist die Schaltfläche Löschen ausgeblendet (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Und wenn ein Administrator zu besucht, hat er Zugriff auf die Schaltflächen Bearbeiten und Löschen.

Die Schaltflächen

Abbildung 15: Die Schaltflächen "Bearbeiten" und "Löschen" sind nur für Administratoren verfügbar (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Schritt 3: Anwenden von Role-Based Autorisierungsregeln auf Klassen und Methoden

In Schritt 2 haben wir die Bearbeitungsfunktionen auf Benutzer in den Rollen Supervisors und Administratoren und Löschfunktionen nur auf Administratoren beschränkt. Dies wurde erreicht, indem die zugeordneten Benutzeroberflächenelemente für nicht autorisierte Benutzer durch programmgesteuerte Techniken ausgeblendet wurden. Solche Maßnahmen garantieren nicht, dass ein nicht autorisierter Benutzer keine privilegierte Aktion ausführen kann. Es kann Benutzeroberflächenelemente geben, die später hinzugefügt werden oder die wir vergessen haben, für nicht autorisierte Benutzer auszublenden. Oder ein Hacker kann eine andere Möglichkeit entdecken, die ASP.NET Seite zu erhalten, um die gewünschte Methode auszuführen.

Eine einfache Möglichkeit, sicherzustellen, dass ein nicht autorisierter Benutzer nicht auf eine bestimmte Funktion zugreifen kann, besteht darin, diese Klasse oder Methode mit dem PrincipalPermission -Attribut zu versehen. Wenn die .NET-Runtime eine Klasse verwendet oder eine ihrer Methoden ausführt, wird überprüft, ob der aktuelle Sicherheitskontext über berechtigungen verfügt. Das PrincipalPermission -Attribut stellt einen Mechanismus bereit, mit dem wir diese Regeln definieren können.

Wir haben uns die Verwendung des PrincipalPermission Attributs im Tutorial zur benutzerbasierten Autorisierung angesehen. Insbesondere haben wir gesehen, wie der -Ereignishandler von GridView SelectedIndexChanged und RowDeleting so ergänzt wird, dass sie nur von authentifizierten Benutzern bzw. Tito ausgeführt werden können. Das PrincipalPermission Attribut funktioniert genauso gut mit Rollen.

Wir veranschaulichen die Verwendung des PrincipalPermission -Attributs für die GridView- RowUpdating und RowDeleting -Ereignishandler, um die Ausführung für nicht autorisierte Benutzer zu verhindern. Alles, was wir tun müssen, ist, das entsprechende Attribut auf jeder Funktionsdefinition hinzuzufügen:

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
[PrincipalPermission(SecurityAction.Demand, Role = "Supervisors")]
protected void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     ...
}

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
protected void UserGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
     ...
}

Das -Attribut für den RowUpdating Ereignishandler schreibt vor, dass nur Benutzer in den Rollen "Administratoren" oder "Supervisors" den Ereignishandler ausführen können, wobei als Attribut für den RowDeleting Ereignishandler die Ausführung auf Benutzer in der Rolle "Administratoren" beschränkt ist.

Hinweis

Das PrincipalPermission Attribut wird als Klasse im System.Security.Permissions Namespace dargestellt. Fügen Sie am Anfang ihrer CodeBehind-Klassendatei eine using System.Security.Permissions -Anweisung hinzu, um diesen Namespace zu importieren.

Wenn ein Nicht-Administrator versucht, den RowDeleting Ereignishandler auszuführen, oder wenn ein Nicht-Supervisor oder Nicht-Administrator versucht, den RowUpdating Ereignishandler auszuführen, löst die .NET-Runtime einen aus SecurityException.

Wenn der Sicherheitskontext nicht autorisiert ist, die Methode auszuführen, wird eine SecurityException ausgelöst.

Abbildung 16: Wenn der Sicherheitskontext nicht autorisiert ist, die Methode auszuführen, wird ein SecurityException ausgelöst (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Neben ASP.NET Seiten verfügen viele Anwendungen auch über eine Architektur, die verschiedene Ebenen umfasst, z. B. Geschäftslogik und Datenzugriffsebenen. Diese Ebenen werden in der Regel als Klassenbibliotheken implementiert und bieten Klassen und Methoden für die Ausführung von geschäftslogik- und datenbezogenen Funktionen. Das PrincipalPermission -Attribut ist auch nützlich, um Autorisierungsregeln auf diese Ebenen anzuwenden.

Weitere Informationen zur Verwendung des Attributs zum Definieren von PrincipalPermission Autorisierungsregeln für Klassen und Methoden finden Sie im Blogeintrag Hinzufügen von Autorisierungsregeln zu Geschäfts- und Datenebenen von Scott Guthrie mit PrincipalPermissionAttributes.

Zusammenfassung

In diesem Tutorial haben wir uns mit der Angabe von groben und feinkörnigen Autorisierungsregeln basierend auf den Rollen des Benutzers befasst. ASP. Mit der URL-Autorisierungsfunktion von NET kann ein Seitenentwickler angeben, welche Identitäten der Zugriff auf welche Seiten zulässig oder verweigert wird. Wie wir bereits im Tutorial zur benutzerbasierten Autorisierung gesehen haben, können URL-Autorisierungsregeln auf Benutzerbasis angewendet werden. Sie können auch rollenweise angewendet werden, wie wir in Schritt 1 dieses Tutorials gesehen haben.

Differenzierte Autorisierungsregeln können deklarativ oder programmgesteuert angewendet werden. In Schritt 2 haben wir die Verwendung der RoleGroups-Funktion des LoginView-Steuerelements untersucht, um basierend auf den Rollen des besuchenden Benutzers unterschiedliche Ausgaben zu rendern. Wir haben auch Möglichkeiten untersucht, wie Sie programmgesteuert ermitteln können, ob ein Benutzer zu einer bestimmten Rolle gehört und wie die Funktionalität der Seite entsprechend angepasst werden kann.

Viel Spaß beim Programmieren!

Weitere Informationen

Weitere Informationen zu den in diesem Tutorial behandelten Themen finden Sie in den folgenden Ressourcen:

Zum Autor

Scott Mitchell, Autor mehrerer ASP/ASP.NET-Bücher und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Scott kann unter mitchell@4guysfromrolla.com oder über seinen Blog unter http://ScottOnWriting.NETerreicht werden.

Besonderer Dank an...

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Zu den leitenden Prüfern für dieses Tutorial gehören Suchi Banerjee und Teresa Murphy. Möchten Sie meine bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter mitchell@4GuysFromRolla.com