Rollenbasierte Autorisierung (VB)
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 Platform anstelle der Mitgliedschaftsanbieter verwenden, die zum Zeitpunkt der Veröffentlichung dieses Artikels vorgestellt wurden. ASP.NET Identity hat 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 für anspruchsbasierte Identitäten
- 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. Danach sehen wir uns die Verwendung deklarativer und programmgesteuerter Mittel zum Ändern der angezeigten Daten und der Funktionalität einer ASP.NET Seite an.
Einführung
Im Tutorial zur benutzerbasierten 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.config
könnten wir ASP.NET anweisen, nur authentifizierten Benutzern den Besuch einer Seite zu gestatten. Oder wir könnten diktieren, dass nur Benutzer Tito und Bob zugelassen wurden, oder dass alle authentifizierten Benutzer mit Ausnahme von Sam zugelassen wurden.
Zusätzlich zur URL-Autorisierung haben wir uns auch mit deklarativen und programmgesteuerten Techniken zur Steuerung der angezeigten Daten und der Funktionalität einer Seite 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-Albtraum werden. Ein besser verwaltbarer Ansatz ist die Verwendung der rollenbasierten Autorisierung. Die gute Nachricht ist, dass die tools, die uns zur Anwendung von Autorisierungsregeln zur Verfügung stehen, 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. Danach sehen wir uns die Verwendung deklarativer und programmgesteuerter Mittel zum Ändern der angezeigten Daten und der Funktionalität einer ASP.NET Seite an. Jetzt geht‘s los!
Grundlegendes zur Zuordnung von Rollen zum Sicherheitskontext eines Benutzers
Wenn eine Anforderung in die ASP.NET-Pipeline eintritt, wird 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 die FormsAuthenticationModule
für die Ermittlung der Identität des Anforderers verantwortlich, was während des EreignissesAuthenticateRequest
der Fall ist.
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, denen er angehört. Dieser Zweck wird dadurch deutlich, dass alle Prinzipalobjekte über eine Identity
-Eigenschaft und eine IsInRole(roleName)
-Methode verfügen. Der FormsAuthenticationModule
ist jedoch nicht an der Aufzeichnung von Rolleninformationen interessiert, und das objekt, das GenericPrincipal
erstellt wird, gibt keine Rollen an.
Wenn das Rollenframework aktiviert ist, tritt das RoleManagerModule
HTTP-Modul nach und FormsAuthenticationModule
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 das RoleManagerModule
GenericPrincipal
von erstellte FormsAuthenticationModule
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. Führt FormsAuthenticationModule
zuerst aus, identifiziert den Benutzer über sein Authentifizierungsticket und erstellt ein neues GenericPrincipal
-Objekt. Als Nächstes überschreiben die RoleManagerModule
Schritte in und das GenericPrincipal
Objekt mit einem RolePrincipal
-Objekt.
Wenn ein anonymer Benutzer die Website besucht, erstellt weder noch FormsAuthenticationModule
ein RoleManagerModule
Prinzipalobjekt.
Abbildung 1: Die ASP.NET Pipelineereignisse für einen authentifizierten Benutzer bei Verwendung der Formularauthentifizierung und des Rollenframeworks (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Zwischenspeichern von Rolleninformationen in einem Cookie
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 SqlRoleProvider
zu einer Abfrage an die Rollenspeicherdatenbank. Bei Verwendung von rollenbasierten URL-Autorisierungsregeln wird die -IsInRole
Methode von RolePrincipal
bei jeder Anforderung an eine Seite aufgerufen, die durch die rollenbasierten URL-Autorisierungsregeln geschützt ist. Anstatt bei jeder Anforderung die Rolleninformationen in der Datenbank nachschlagen zu müssen, enthält das Roles
Framework eine Option zum Zwischenspeichern der Benutzerrollen in einem Cookie.
Wenn das Rollenframework so konfiguriert ist, dass die Rollen des Benutzers in einem Cookie zwischengespeichert werden, wird das RoleManagerModule
Cookie während des EreignissesEndRequest
der ASP.NET Pipeline erstellt. Dieses Cookie wird in nachfolgenden Anforderungen in verwendet, wenn PostAuthenticateRequest
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 verhindert, dass die RolePrincipal
-Klasse aufgerufen werden muss, Roles
um die Rollen des Benutzers zu bestimmen. Abbildung 2 zeigt diesen Workflow.
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)
Der Cookiemechanismus für den Rollencache ist standardmäßig deaktiviert. Sie kann über das <roleManager>
-Konfigurationsmarkup in Web.config
aktiviert 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 Cookieeinstellungen für den Rollencache 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 Cookiezwischenspeicherung verwendet wird. Der Standardwert lautet false . |
cookieName |
Der Name des Rollencachecookies. Der Standardwert ist ". ASPXROLES". |
cookiePath |
Der Pfad für das Rollennamen-Cookie. Mit dem Path-Attribut kann ein Entwickler den Bereich eines Cookies auf eine bestimmte Verzeichnishierarchie 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. Zulässige Werte sind: All (Standard); Encryption ; None und Validation .md) |
| cookieRequireSSL
| Ein boolescher Wert, der angibt, ob eine SSL-Verbindung erforderlich ist, um das Authentifizierungscookies zu übertragen. Der Standardwert ist false cookieSlidingExpiration false createPersistentCookieis set to
true. | |
cookieTimeout | Specifies the time, in minutes, after which the authentication ticket cookie expires. The default value is
30. This value is only pertinent when
createPersistentCookieis set to
true. | |
createPersistentCookie | A Boolean value that specifies whether the role cache cookie is a session cookie or persistent cookie. If
false, a persistent cookie is used; it expires
(the default), a session cookie is used, which is deleted when the browser is closed. If
cookieTimeoutnumber of minutes after it has been created or after the previous visit, depending on the value of
cookieSlidingExpiration. | |
domain| Specifies the cookie's domain value. The default value is an empty string, which causes the browser to use the domain from which it was issued (such as www.yourdomain.com). In this case, the cookie will <strong>not</strong> be sent when making requests to subdomains, such as admin.yourdomain.com. If you want the cookie to be passed to all subdomains you need to customize the
domainattribute, setting it to "yourdomain.com". | |
maxCachedResults | Specifies the maximum number of role names that are cached in the cookie. The default is 25. The
RoleManagerModule maxCachedResults RoleManagerModuledoes not create a cookie for users that belong to more than
maxCachedResultsroles. Consequently, the
RolePrincipalobject's
IsInRolemethod will use the
Rolesclass to determine the user's roles. The reason
maxCachedResultsexists is because many user agents do not permit cookies larger than 4,096 bytes. So this cap is meant to reduce the likelihood of exceeding this size limitation. If you have extremely long role names, you may want to consider specifying a smaller
. This value is only pertinent when
| A Boolean value that indicates whether the cookie's timeout is reset each time the user visits the site during a single session. The default value is
. | |
maxCachedResults-Wert; 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
, createPersistentCookie
und cookieProtection
. Wenn Sie auf true
festlegencacheRolesInCookie
, 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 weiteren Sicherheitsbedenken finden Sie in der Sicherheitsfrageliste für ASP.NET 2.0.
Schritt 1: Definieren Role-Based URL-Autorisierungsregeln
Wie im Tutorial "Benutzerbasierte Autorisierung" erläutert, bietet die URL-Autorisierung eine Möglichkeit, den Zugriff auf eine Reihe von Seiten auf Benutzer- oder Rollenbasis zu beschränken. Die URL-Autorisierungsregeln werden in Web.config
der Verwendung des <authorization>
Elements mit <allow>
und <deny>
untergeordneten Elementen beschrieben. Zusätzlich zu den benutzerbezogenen Autorisierungsregeln, die in früheren 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 den 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.aspx
Seiten , UsersAndRoles.aspx
und CreateUserWizardWithRoles.aspx
nur für diese 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, fügen Sie dem Roles
Ordner eine Datei hinzuWeb.config
.
Abbildung 3: Hinzufügen einer Web.config
Datei zum Verzeichnis (Klicken Sie hier, um dasRoles
Bild in voller Größe anzuzeigen)
Fügen Sie als Nächstes das folgende Konfigurationsmarkup 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 in 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.
Melden Sie sich nach dem Speichern Ihrer Änderungen in Web.config
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
Daher 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 an, UnauthorizedAccess.aspx
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.
Abbildung 4: Nur Benutzer in der Rolle "Administratoren" 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 sich in der Rolle Administratoren befindet. Nun sollten Sie die drei geschützten Seiten anzeigen können.
Abbildung 5: Tito kann die UsersAndRoles.aspx
Seite besuchen, da er sich in der Administratorrolle 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 <allow>
- oder <deny>
-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, ist es daher unerlässlich, dass Sie ein <deny>
Element als letztes Element in der URL-Autorisierungskonfiguration verwenden. Wenn Ihre URL-Autorisierungsregeln keine<deny>
-Element, allen Benutzern wird Zugriff gewährt. Eine ausführlichere Diskussion darüber, wie die URL-Autorisierungsregeln analysiert werden, finden Sie im Abschnitt "A Look on how the Uses the UrlAuthorizationModule
Authorization Rules to Grant or Deny Access" im Tutorial Zur benutzerbasierten Autorisierung.
Schritt 2: Einschränken der Funktionalität basierend auf den Aktuell angemeldeten Benutzerrollen
Die URL-Autorisierung macht es einfach, grobe Autorisierungsregeln anzugeben, die angeben, welche Identitäten zulässig sind und welchen Identitäten das Anzeigen einer bestimmten Seite (oder aller Seiten in einem Ordner und seinen Unterordnern) verweigert wird. In bestimmten Fällen möchten wir jedoch allen Benutzern den Besuch einer Seite erlauben, aber die Funktionalität der Seite basierend auf den Rollen des besuchenden Benutzers einschränken. Dies kann das Anzeigen oder Ausblenden von Daten basierend auf der Rolle des Benutzers oder das Anbieten zusätzlicher Funktionen für Benutzer, die zu einer bestimmten Rolle gehören, umfassen.
Solche feinkörnigen rollenbasierten Autorisierungsregeln können entweder deklarativ oder programmgesteuert (oder durch eine Kombination der beiden) implementiert werden. Im nächsten Abschnitt erfahren Sie, wie Sie die deklarative Feinkornautorisierung über das LoginView-Steuerelement implementieren. Anschließend werden wir programmgesteuerte Techniken untersuchen. Bevor wir uns jedoch mit der Anwendung feiner Autorisierungsregeln befassen können, müssen wir zuerst eine Seite erstellen, deren Funktionalität von der Rolle des Benutzers abhängt, der sie besucht.
Erstellen Sie 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 die GridView die Bearbeitungs- und Löschfunktionen. Zunächst erstellen wir diese Seite mit der Bearbeitungs- und Löschfunktion, die allen Benutzern zur Verfügung steht. In den Abschnitten "Verwenden des LoginView-Steuerelements" und "Programmgesteuertes Einschränken der Funktionalität" erfahren Sie, wie Sie diese Features basierend auf der Rolle des besuchenden Benutzers 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 Anleitungen zum Einrichten dieser Seite, geht aber nicht darauf ein, 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 eine GridView von der Seite auf die Designer, und legen Sie sie ID
auf festUserGrid
. In einem Moment schreiben wir Code, der das Membership
aufruft.GetAllUsers
und bindet das resultierende MembershipUserCollection
Objekt an die GridView. Enthält MembershipUserCollection
ein Objekt für jedes Benutzerkonto im System. MembershipUser
Objekte verfügen über Eigenschaften wie UserName
uswEmail
LastLoginDate
.MembershipUser
Bevor wir den Code schreiben, der die Benutzerkonten an das Raster bindet, definieren wir zunächst die Felder von GridView. 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 linken unteren Ecke. Da diese GridView Bearbeitungs- und Löschfunktionen enthalten soll, fügen Sie ein CommandField-Element hinzu, und legen Sie dessen ShowEditButton
Eigenschaften und ShowDeleteButton
auf True fest. Fügen Sie als Nächstes vier Felder zum Anzeigen der UserName
Eigenschaften , Email
, LastLoginDate
und Comment
hinzu. Verwenden Sie boundField für die beiden schreibgeschützten Eigenschaften (UserName
und LastLoginDate
) und TemplateFields für die beiden bearbeitbaren Felder (Email
und Comment
).
Lassen Sie das erste BoundField die UserName
-Eigenschaft anzeigen; legen Sie die HeaderText
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 es HeaderText
auf "Letzte Anmeldung" und auf DataField
"LastLoginDate" festlegen. Formatieren Sie die Ausgabe dieses BoundField so, dass nur das Datum (anstelle von Datum und Uhrzeit) angezeigt wird. Legen Sie dazu die Eigenschaft dieser BoundField-Eigenschaft HtmlEncode
auf False und ihre 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.
Abbildung 6: Die Felder von GridView können über das Dialogfeld Felder konfiguriert werden (Klicken Sie, um das bild in voller Größe anzuzeigen)
Nun müssen wir das und EditItemTemplate
für die ItemTemplate
TemplateFields "Email" und "Comment" definieren. Fügen Sie jedem von ItemTemplates
ein Label-Websteuerelement hinzu, und binden Sie deren Text
Eigenschaften an die Eigenschaften bzwComment
. die Email
Eigenschaften.
Fügen Sie für das TemplateField "Email" ein TextBox-Element mit dem Namen Email
hinzuEditItemTemplate
, und binden Sie seine Text
Eigenschaft mithilfe der bidirektionalen Datenbindung an die Email
-Eigenschaft. Fügen Sie einen RequiredFieldValidator und Einen RegularExpressionValidator hinzuEditItemTemplate
, um sicherzustellen, dass ein Besucher, der die Email-Eigenschaft bearbeitet, eine gültige E-Mail-Adresse eingegeben hat. Fügen Sie für das TemplateField "Kommentar" ein mehrzeiliges TextBox-Element mit dem Namen Comment
hinzu EditItemTemplate
. Legen Sie die Eigenschaften und des TextBox-Objekts Columns
auf 40 bzw. 4 fest, und binden Text
Sie die Eigenschaft dann mithilfe der bidirektionalen Datenbindung an die Comment
-Eigenschaft.Rows
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 GridView-Eigenschaft DataKeyNames
auf "UserName" fest, damit diese Informationen über die GridView-Auflistung DataKeys
verfügbar sind.
Fügen Sie schließlich der Seite ein ValidationSummary-Steuerelement hinzu, und legen Sie seine 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 die GridView zu binden. Fügen Sie der CodeBehind-Klasse der RoleBasedAuthorization.aspx
Seite eine Methode mit dem Namen BindUserGrid
hinzu, die das MembershipUserCollection
zurückgegebene von Membership.GetAllUsers
an die UserGrid
GridView bindet. Rufen Sie diese Methode beim ersten Seitenbesuch aus dem Page_Load
Ereignishandler auf.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
BindUserGrid()
End If
End Sub
Private Sub BindUserGrid()
Dim allUsers As MembershipUserCollection = Membership.GetAllUsers()
UserGrid.DataSource = allUsers
UserGrid.DataBind()
End Sub
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.
Abbildung 7: GridView UserGrid
listet Informationen zu jedem Benutzer im System auf (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Hinweis
Die UserGrid
GridView 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 Option besteht darin, gridView so zu konfigurieren, dass das 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 übernimmt 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 die Benutzer anzeigt, deren Benutzername mit einem ausgewählten Zeichen beginnt, für instance. Die Membership.FindUsersByName
Methode eignet sich ideal zum Erstellen einer filterbasierten Benutzeroberfläche. Wir werden uns das Erstellen einer solchen Schnittstelle in einem zukünftigen Tutorial ansehen.
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
GridView ist jedoch programmgesteuert an die Daten gebunden. Daher müssen wir Code schreiben, um diese beiden Aufgaben auszuführen. Insbesondere müssen wir Ereignishandler für die GridView-Ereignisse RowEditing
, RowCancelingEdit
, , RowUpdating
und erstellen, die RowDeleting
ausgelöst werden, wenn ein Besucher auf die Schaltflächen Bearbeiten, Abbrechen, Aktualisieren oder Löschen von GridView klickt.
Erstellen Sie zunächst die Ereignishandler für die GridView-Ereignisse RowEditing
, RowCancelingEdit
und RowUpdating
fügen Sie dann den folgenden Code hinzu:
Protected Sub UserGrid_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles UserGrid.RowEditing
' Set the grid's EditIndex and rebind the data
UserGrid.EditIndex = e.NewEditIndex
BindUserGrid()
End Sub
Protected Sub UserGrid_RowCancelingEdit(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles UserGrid.RowCancelingEdit
' Revert the grid's EditIndex to -1 and rebind the data
UserGrid.EditIndex = -1
BindUserGrid()
End Sub
Protected Sub UserGrid_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles UserGrid.RowUpdating
' Exit if the page is not valid
If Not Page.IsValid Then
Exit Sub
End If
' Determine the username of the user we are editing
Dim UserName As String = UserGrid.DataKeys(e.RowIndex).Value.ToString()
' Read in the entered information and update the user
Dim EmailTextBox As TextBox = CType(UserGrid.Rows(e.RowIndex).FindControl("Email"),TextBox)
Dim CommentTextBox As TextBox= CType(UserGrid.Rows(e.RowIndex).FindControl("Comment"),TextBox)
' Return information about the user
Dim UserInfo As MembershipUser = 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()
End Sub
Die RowEditing
Ereignishandler und RowCancelingEdit
legen einfach die GridView-Eigenschaft EditIndex
fest und binden dann die Liste der Benutzerkonten erneut an das Raster. Das Interessante geschieht 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 Textfelder 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 tun Membership.GetUser(userName)
. Die Eigenschaften des zurückgegebenen MembershipUser
Objekts Email
und Comment
werden dann mit den Werten aktualisiert, die über die Bearbeitungsschnittstelle in die beiden TextBoxes eingegeben werden. Schließlich werden diese Änderungen mit einem Aufruf von Membership.UpdateUser
gespeichert. Der RowUpdating
Ereignishandler wird abgeschlossen, indem die GridView auf die Schnittstelle vor der Bearbeitung zurückgesetzt wird.
Erstellen Sie als Nächstes den RowDeleting
RowDeleting-Ereignishandler, und fügen Sie dann den folgenden Code hinzu:
Protected Sub UserGrid_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles UserGrid.RowDeleting
' Determine the username of the user we are editing
Dim UserName As String = 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()
End Sub
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. den Rollen, zu der 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 aufgerufen wird.
Hinweis
Die Schaltfläche Löschen erfordert keine Bestätigung des Benutzers, 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 zum Bestätigen einer Aktion ist ein clientseitiges Bestätigungsdialogfeld. Weitere Informationen zu diesem Verfahren finden Sie unter Hinzufügen Client-Side Bestätigung beim Löschen.
Vergewissern Sie sich, dass diese Seite wie erwartet funktioniert. Sie sollten in der Lage sein, die E-Mail-Adresse und den Kommentar eines beliebigen 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 den Kommentar 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 anweisungen anzuzeigen, die für die Rolle des Benutzers gelten. Wenn eine Person in der Rolle Administratoren diese Seite besucht, werden Anweisungen zum Bearbeiten und Löschen von Benutzern angezeigt. Wenn ein Benutzer in der Rolle "Supervisors" diese Seite erreicht, werden Anweisungen zum Bearbeiten von Benutzern angezeigt. Wenn der Besucher anonym ist oder nicht in der Rolle "Vorgesetzte" 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 verschiedene Markups basierend auf den Rollen des Benutzers anzuzeigen. Verwenden Sie ein LoginView-Steuerelement, um verschiedene Anweisungen basierend auf der Rolle des besuchenden Benutzers anzuzeigen.
Beginnen Sie mit dem Hinzufügen einer LoginView über der UserGrid
GridView. Wie bereits erläutert, verfügt das LoginView-Steuerelement über zwei integrierte Vorlagen: AnonymousTemplate
und LoggedInTemplate
. Geben Sie in beiden Vorlagen eine kurze Nachricht 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 und AnonymousTemplate
LoggedInTemplate
kann das LoginView-Steuerelement RoleGroups enthalten, bei denen es sich um rollenspezifische Vorlagen handelt. Jede RoleGroup enthält eine einzelne Eigenschaft, die angibt, Roles
auf 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 aufzurufen. Fügen Sie zwei neue RoleGroups hinzu. Legen Sie die Eigenschaft der ersten RoleGroup Roles
auf "Administratoren" und die zweite auf "Supervisors" fest.
Abbildung 8: Verwalten der Role-Specific-Vorlagen der LoginView über den RoleGroup-Sammlungs-Editor (Klicken Sie hier, um das vollständige Bild anzuzeigen)
Klicken Sie auf OK, um den Rollengruppensammlungs-Editor zu schließen. dadurch wird das deklarative Markup von LoginView aktualisiert, soweit es einen Abschnitt mit einem <RoleGroups>
<asp:RoleGroup>
untergeordneten Element für jede RoleGroup enthält, die im RoleGroup-Sammlungs-Editor definiert ist. Darüber hinaus enthält die Dropdownliste "Ansichten" im Smarttag der LoginView, in der zunächst nur das AnonymousTemplate
und LoggedInTemplate
aufgeführt wurde, nun auch die hinzugefügten Rollengruppen.
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 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' 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 angezeigt werden: "Sie sind kein Mitglied der Rolle Vorgesetzte oder Administratoren. 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 in der Rolle "Administratoren" anmelden, sollte die Meldung Administratorrollenspezifische Meldung angezeigt werden (siehe Abbildung 10).
Abbildung 9: Bruce wird die Role-Specific-Nachricht von Supervisors angezeigt (Klicken Sie, um das bild in voller Größe anzuzeigen)
Abbildung 10: Tito zeigt die Meldung "Administratoren Role-Specific" (Klicken Sie hier, um das bild in voller Größe anzuzeigen)
Wie die Screenshots in Abbildungen 9 und 10 zeigen, rendert die LoginView nur eine Vorlage, auch wenn mehrere Vorlagen angewendet werden. Bruce und Tito sind beide Benutzer angemeldet, aber die LoginView rendert nur die übereinstimmende RoleGroup und nicht die LoggedInTemplate
. Darüber hinaus gehört Tito sowohl zur Rolle Administratoren als auch zu den Vorgesetzten, 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. Mit anderen Worten, wenn wir die Supervisors RoleGroup als erste Rollengruppe und die Administratoren als zweite platziert hätten, würde Tito diese Seite besuchen, die Meldung Supervisors angezeigt.
Abbildung 11: Workflow des LoginView-Steuerelements zum Bestimmen der zu rendernden Vorlage (Klicken, 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 programmgesteuert für anonyme Besucher und Benutzer ausblenden, die sich weder in der Rolle "Supervisors" noch "Administratoren" befinden. Wir müssen die Schaltfläche Löschen für alle 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 False
festlegt.
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 das CommandField aus der Liste der aktuellen Felder aus, und klicken Sie auf den Link "Dieses Feld in ein TemplateField konvertieren". Dadurch wird das CommandField-Objekt in ein TemplateField-Objekt mit ItemTemplate
und EditItemTemplate
umgewandelt. Enthält ItemTemplate
die LinkButtons bearbeiten und löschen, während die EditItemTemplate
LinkButtons Aktualisieren und Abbrechen enthält.
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 , ItemTemplate
und legen Sie ihre 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 die GridView gebunden sind, zählt gridView die Datensätze in seiner DataSource
Eigenschaft auf und generiert ein entsprechendes GridViewRow
Objekt. Während 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 Sub UserGrid_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles UserGrid.RowCreated
If e.Row.RowType = DataControlRowType.DataRow AndAlso e.Row.RowIndex <> UserGrid.EditIndex Then
' Programmatically reference the Edit and Delete LinkButtons
Dim EditButton As LinkButton = CType(e.Row.FindControl("EditButton"), LinkButton)
Dim DeleteButton As LinkButton = CType(e.Row.FindControl("DeleteButton"), LinkButton)
EditButton.Visible = (User.IsInRole("Administrators") OrElse User.IsInRole("Supervisors"))
DeleteButton.Visible = User.IsInRole("Administrators")
End If
End Sub
Beachten Sie, dass das RowCreated
Ereignis für alle GridView-Zeilen ausgelöst wird, einschließlich der Kopfzeile, der Fußzeile, der 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 Bearbeiten und Löschen verwiesen, und ihre Visible
Eigenschaften werden basierend auf den booleschen Werten festgelegt, die von der Methode des User
IsInRole(roleName)
Objekts zurückgegeben werden. Das User
-Objekt verweist auf den Prinzipal, der RoleManagerModule
von 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 und den Aufruf User.IsInRole(roleName)
von durch einen Aufruf der Roles.IsUserInRole(roleName)
-Methode ersetzen können. Ich habe mich in diesem Beispiel für die Verwendung der Methode des IsInRole(roleName)
Prinzipals 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 einen Trip 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 beim ersten Aufruf während einer Anforderung die Ergebnisse zwischengespeichert werden. Die Rollen-API führt dagegen keine Zwischenspeicherung durch. Da das RowCreated
Ereignis für jede Zeile in GridView einmal ausgelöst wird, umfasst die Verwendung User.IsInRole(roleName)
nur eine Fahrt 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 sich der Benutzer, der diese Seite besucht, in der Rolle "Administratoren" oder "Supervisors" befindet. Andernfalls ist sie auf False
festgelegt. Die Eigenschaft der Visible
Schaltfläche Löschen ist nur auf True
festgelegt, wenn sich der Benutzer in der Rolle "Administratoren" befindet.
Testen Sie diese Seite über einen Browser. Wenn Sie die Seite als anonymer Besucher oder als Benutzer besuchen, der weder Supervisor noch 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.
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 nur die Schaltfläche Bearbeiten angezeigt.
Abbildung 14: Während die Schaltfläche Bearbeiten für Supervisors 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 besucht, hat er Zugriff auf die Schaltflächen Bearbeiten und Löschen.
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 Role-Based Autorisierungsregeln auf Klassen und Methoden
In Schritt 2 haben wir die Bearbeitungsfunktionen auf Benutzer in den Rollen "Supervisors" und "Administratoren" beschränkt und funktionen nur auf Administratoren gelöscht. Dies wurde erreicht, indem die zugehörigen Benutzeroberflächenelemente für nicht autorisierte Benutzer mithilfe programmgesteuerter Techniken ausgeblendet wurden. Solche Maßnahmen garantieren nicht, dass ein nicht autorisierter Benutzer keine privilegierte Aktion ausführen kann. Möglicherweise gibt es Elemente der Benutzeroberfläche, 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, um 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, über den wir diese Regeln definieren können.
Wir haben uns die Verwendung des PrincipalPermission
Attributs im Tutorial "Benutzerbasierte Autorisierung" angesehen. Insbesondere haben wir gesehen, wie der GridView-Ereignishandler SelectedIndexChanged
und RowDeleting
der Ereignishandler so gestaltet werden, dass sie nur von authentifizierten Benutzern bzw. Tito ausgeführt werden konnten. Das PrincipalPermission
Attribut funktioniert genauso gut mit Rollen.
Wir veranschaulichen die Verwendung des PrincipalPermission
Attributs RowUpdating
für die GridView- und RowDeleting
-Ereignishandler, um die Ausführung für nicht autorisierte Benutzer zu verhindern. Alles, was wir tun müssen, ist, das entsprechende Attribut zu jeder Funktionsdefinition hinzuzufügen:
<PrincipalPermission(SecurityAction.Demand, Role:="Administrators")>_
<PrincipalPermission(SecurityAction.Demand, Role:="Supervisors")>_
Protected Sub UserGrid_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles UserGrid.RowUpdating
...
End Sub
<PrincipalPermission(SecurityAction.Demand, Role:="Administrators")>_
Protected Sub UserGrid_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles UserGrid.RowDeleting
...
End Sub
Das -Attribut für den RowUpdating
Ereignishandler legt fest, dass nur Benutzer in der Rolle Administratoren oder Betreuer den Ereignishandler ausführen können, wobei die Ausführung als Attribut für den RowDeleting
Ereignishandler 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 Imports 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
.
Abbildung 16: Wenn der Sicherheitskontext nicht zum Ausführen der Methode autorisiert ist, wird ein SecurityException
ausgelöst (Klicken Sie, um das vollständige Bild anzuzeigen)
Neben ASP.NET Seiten verfügen viele Anwendungen auch über eine Architektur, die verschiedene Ebenen wie Geschäftslogik und Datenzugriffsebenen umfasst. 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 unter Scott Guthries Blogeintrag Hinzufügen von Autorisierungsregeln zu Geschäfts- und Datenebenen mit PrincipalPermissionAttributes
.
Zusammenfassung
In diesem Tutorial haben wir uns mit der Angabe grober und feiner Autorisierungsregeln basierend auf den Rollen des Benutzers befasst. ASP. Die URL-Autorisierungsfunktion von NET ermöglicht es einem Seitenentwickler, anzugeben, welche Identitäten der Zugriff auf welche Seiten zulässig oder verweigert wird. Wie wir im Tutorial " Benutzerbasierte Autorisierung" gezeigt haben, können URL-Autorisierungsregeln auf Benutzerbasis angewendet werden. Sie können auch rollenweise angewendet werden, wie wir in Schritt 1 dieses Tutorials gezeigt haben.
Differenzierte Autorisierungsregeln können deklarativ oder programmgesteuert angewendet werden. In Schritt 2 haben wir die Verwendung des RoleGroups-Features des LoginView-Steuerelements untersucht, um eine andere Ausgabe basierend auf den Rollen des besuchenden Benutzers zu rendern. Außerdem wurde 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 erläuterten Themen finden Sie in den folgenden Ressourcen:
- Hinzufügen von Autorisierungsregeln zu Geschäfts- und Datenebenen mithilfe
PrincipalPermissionAttributes
- Untersuchen ASP.NET Mitgliedschaft, Rollen und Profils von ASP.NET 2.0: Arbeiten mit Rollen
- Sicherheitsfrageliste für ASP.NET 2.0
- Technische Dokumentation für das
<roleManager>
Element
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 Stunden. Scott kann unter mitchell@4guysfromrolla.com oder über seinen Blog unter http://ScottOnWriting.NETerreicht werden.
Besonderen 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 anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie mir eine Zeile unter mitchell@4GuysFromRolla.com