Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
von Scott Mitchell
Hinweis
Seit der Erstellung dieses Artikels wurden die ASP.NET Mitgliedschaftsanbieter durch ASP.NET Identityersetzt. Es wird dringend empfohlen, Apps so zu aktualisieren, dass sie die ASP.NET Identity Platform anstelle der Mitgliedschaftsanbieter verwenden, die zu dem Zeitpunkt 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 Claims-basierte Identitäten
- Bessere Interoperabilität mit ASP.Net Core
Code herunterladen oder PDF herunterladen
Dieses Lernprogramm beginnt mit einem Blick darauf, wie das Rollenframework den Rollen eines Benutzers seinem Sicherheitskontext zuordnet. Anschließend wird untersucht, wie rollenbasierte URL-Autorisierungsregeln angewendet werden. Danach werden wir uns mit deklarativen und programmgesteuerten Mitteln befassen, um die angezeigten Daten und die Funktionalität zu ändern, die von einer ASP.NET Seite angeboten wird.
Einführung
ImUser-Based Autorisierungs-Lernprogramm haben wir erfahren, wie Sie die URL-Autorisierung verwenden, um anzugeben, welche Benutzer eine bestimmte Gruppe von Seiten besuchen können. Mit nur wenigen Markups Web.configkonnten wir ASP.NET anweisen, nur authentifizierten Benutzern den Besuch einer Seite zu ermöglichen. Oder wir könnten diktieren, dass nur Benutzer Tito und Bob zulässig waren oder angeben, dass alle authentifizierten Benutzer außer Sam zulässig waren.
Zusätzlich zur URL-Autorisierung haben wir uns auch deklarative und programmatische Techniken zum Steuern der angezeigten Daten und die Funktionalität einer Seite basierend auf dem Besuch des Benutzers angesehen. Insbesondere haben wir eine Seite erstellt, die den Inhalt des aktuellen Verzeichnisses aufgelistet hat. 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ührungsaltraum wachsen. Ein bearbeitbarerer Ansatz besteht darin, die rollenbasierte Autorisierung zu verwenden. Die gute Nachricht ist, dass die Tools, die für die Anwendung von Autorisierungsregeln zur Verfügung stehen, genauso gut mit Rollen funktionieren wie für Benutzerkonten. URL-Autorisierungsregeln können Rollen anstelle von Benutzern angeben. Das LoginView-Steuerelement, das verschiedene Ausgaben für authentifizierte und anonyme Benutzer rendert, kann so konfiguriert werden, dass verschiedene Inhalte basierend auf den Rollen des angemeldeten Benutzers angezeigt werden. Außerdem enthält die Rollen-API Methoden zum Ermitteln der Rollen des angemeldeten Benutzers.
Dieses Lernprogramm beginnt mit einem Blick darauf, wie das Rollenframework den Rollen eines Benutzers seinem Sicherheitskontext zuordnet. Anschließend wird untersucht, wie rollenbasierte URL-Autorisierungsregeln angewendet werden. Danach werden wir uns mit deklarativen und programmgesteuerten Mitteln befassen, um die angezeigten Daten und die Funktionalität zu ändern, die von einer ASP.NET Seite angeboten wird. Fangen wir an!
Grundlegendes dazu, wie Rollen dem Sicherheitskontext eines Benutzers zugeordnet sind
Wenn eine Anforderung die ASP.NET Pipeline eingibt, 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 wir im Lernprogramm "Übersicht über die Formularauthentifizierung " erläutert haben, ist dies FormsAuthenticationModule für die Ermittlung der Identität des Anforderers verantwortlich, die er während des AuthenticateRequest Ereignisses ausführt.
Wenn ein gültiges, nicht abgelaufenes Authentifizierungsticket gefunden wird, decodiert es, FormsAuthenticationModule um die Identität des Antragstellers zu ermitteln. Es erstellt ein neues GenericPrincipal Objekt und weist dieses dem HttpContext.User Objekt zu. Der Zweck eines Prinzipals wie GenericPrincipal ist es, den Namen des authentifizierten Benutzers zu identifizieren und die Rollen, denen er angehört. Dieser Zweck ist durch die Tatsache ersichtlich, dass alle Prinzipalobjekte eine Identity Eigenschaft und eine IsInRole(roleName) Methode haben. Das FormsAuthenticationModule ist jedoch nicht daran interessiert, Rolleninformationen aufzuzeichnen, und das Objekt, das GenericPrincipal erstellt, gibt keine Rollen an.
Wenn das Rollenframework aktiviert ist, tritt das RoleManagerModule HTTP-Modul nach dem FormsAuthenticationModule Ereignis in Aktion 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 RoleManagerModule das GenericPrincipal von dem FormsAuthenticationModule Objekt 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 Pipelineworkflow bei Verwendung der Formularauthentifizierung und des Rollenframeworks. Die FormsAuthenticationModule Ausführung erfolgt zuerst, identifiziert den Benutzer über ihr Authentifizierungsticket und erstellt ein neues GenericPrincipal Objekt. Als Nächstes tritt RoleManagerModule in Aktion und überschreibt das GenericPrincipal Objekt mit einem RolePrincipal Objekt.
Wenn ein anonymer Benutzer die Website besucht, erstellt weder das FormsAuthenticationModule- noch das RoleManagerModule-Element ein Principal-Objekt.
Abbildung 1: Die ASP.NET Pipelineereignisse für einen authentifizierten Benutzer bei Verwendung der Formularauthentifizierung und des Rollenframeworks (Klicken Sie hier, um das Bild mit 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. Wenn Sie die SqlRoleProvider verwenden, führt dies zu einer Abfrage an die Rollenspeicherdatenbank. Bei Verwendung rollenbasierter URL-Autorisierungsregeln wird die RolePrincipalIsInRole Methode für jede Anforderung an eine Seite aufgerufen, die durch die rollenbasierten URL-Autorisierungsregeln geschützt ist. Anstatt die Rolleninformationen in der Datenbank auf jeder Anforderung nachzuschlagen, enthält das Roles Framework 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, erstellt das RoleManagerModule Cookie während des EreignissesEndRequest der ASP.NET Pipeline. Dieses Cookie wird in den nachfolgenden Anfragen innerhalb des PostAuthenticateRequest verwendet, wenn 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, wodurch verhindert wird, dass die RolePrincipal Klasse aufgerufen Roles werden muss, um die Rollen des Benutzers zu ermitteln. 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)
Standardmäßig ist der Rollencache-Cookiemechanismus deaktiviert. Es kann durch das <roleManager>-Konfigurationsmarkup in Web.config aktiviert werden. Wir haben die Verwendung des Elements zum Angeben von <roleManager> Rollenanbietern im Lernprogramm zum Erstellen und Verwalten von Rollen besprochen. Daher sollten Sie dieses Element bereits in der Datei Ihrer Anwendung Web.config haben. Die Einstellungen des Rollencache-Cookies 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 Lernprogramm zu Cookies.
| Eigentum | Beschreibung |
|---|---|
cacheRolesInCookie |
Ein boolescher Wert, der angibt, ob das Zwischenspeichern von Cookies verwendet wird. Wird standardmäßig auf false festgelegt. |
cookieName |
Der Name des Rollen-Cache-Cookies. Der Standardwert ist ". ASPXROLES". |
cookiePath |
Der Pfad für das Rollennamen-Cookie. Mit dem Path-Attribut kann ein Entwickler den Umfang eines Cookies auf eine bestimmte Verzeichnishierarchie beschränken. Der Standardwert ist "/", dies informiert den Browser, 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 (Standard); Encryption; ; Noneund ValidationMD) |
|
cookieRequireSSL | Ein boolescher Wert, der angibt, ob eine SSL-Verbindung zum Übertragen des Authentifizierungscookies erforderlich ist. Der Standardwert ist false. | | cookieSlidingExpiration | 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 isfalse. This value is only pertinent when createPersistentCookieis set totrue. | | cookieTimeout | Specifies the time, in minutes, after which the authentication ticket cookie expires. The default value is30. This value is only pertinent when createPersistentCookieis set totrue. | | createPersistentCookie | A Boolean value that specifies whether the role cache cookie is a session cookie or persistent cookie. Iffalse(the default), a session cookie is used, which is deleted when the browser is closed. Iftrue, a persistent cookie is used; it expires cookieTimeoutnumber of minutes after it has been created or after the previous visit, depending on the value ofcookieSlidingExpiration. | | 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 thedomainattribute, setting it to "yourdomain.com". | | maxCachedResults | Specifies the maximum number of role names that are cached in the cookie. The default is 25. TheRoleManagerModuledoes not create a cookie for users that belong to more thanmaxCachedResultsroles. Consequently, theRolePrincipalobject'sIsInRolemethod will use theRolesclass to determine the user's roles. The reasonmaxCachedResultsexists 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 smallermaxCachedResults'-Wert; umgekehrt, wenn Sie extrem kurze Rollennamen haben, können Sie diesen Wert wahrscheinlich erhöhen. |
Tabelle 1: Konfigurationsoptionen für Rollencache-Cookies
Konfigurieren wir unsere Anwendung so, dass nicht persistente Rollencache-Cookies verwendet werden. Aktualisieren Sie dazu das <roleManager> Element Web.config so, dass es die folgenden cookiebezogenen Attribute enthält:
<roleManager enabled="true"
defaultProvider="SecurityTutorialsSqlRoleProvider"
cacheRolesInCookie="true"
createPersistentCookie="false"
cookieProtection="All">
<providers>
...
</providers>
</roleManager>
Das <roleManager>-Element wurde aktualisiert, indem drei Attribute hinzugefügt wurden: cacheRolesInCookie, createPersistentCookie und cookieProtection. Durch das Festlegen von cacheRolesInCookie auf true wird die Rolle des Benutzers vom RoleManagerModule jetzt automatisch in einem Cookie zwischengespeichert, anstatt die Rolleninformationen des Benutzers bei jeder Anforderung abzurufen. Ich habe die Attribute createPersistentCookie und cookieProtection explizit auf false bzw. All festgelegt. Technisch gesehen musste ich keine Werte für diese Attribute angeben, da ich sie soeben ihren Standardwerten zugewiesen habe, aber ich habe sie hier platziert, um explizit klarzustellen, dass ich keine persistenten Cookies verwende und dass der Cookie sowohl verschlüsselt als auch validiert ist.
Das ist alles! Daher speichert das Rollenframework die Rollen der Benutzer in Cookies zwischen. Wenn der Browser des Benutzers Cookies nicht unterstützt oder seine Cookies gelöscht oder verloren gehen, ist es kein großes Problem – das RolePrincipal-Objekt verwendet einfach die Roles-Klasse, wenn kein Cookie verfügbar ist (oder ein ungültiges oder abgelaufenes).
Hinweis
Die Gruppe "Patterns & Practices" von Microsoft rät von der Verwendung von Cookies für einen beständigen Rollencache ab. Da der Besitz des Rollen-Cache-Cookies ausreicht, um die Rollenmitgliedschaft zu beweisen, kann ein Hacker, wenn er irgendwie Zugriff auf das Cookie eines gültigen Benutzers erhält, diesen Benutzer imitieren. Die Wahrscheinlichkeit, dass dies geschieht, erhöht sich, wenn das Cookie im Browser des Benutzers beibehalten wird. Weitere Informationen zu dieser Sicherheitsempfehlung sowie zu anderen Sicherheitsbedenken finden Sie in der Sicherheitsfrageliste für ASP.NET 2.0.
Schritt 1: Definieren der rollenbasierten URL-Autorisierungsregeln
Wie im Benutzerbasierte Autorisierung-Lernprogramm erläutert, bietet die URL-Autorisierung eine Möglichkeit, den Zugriff auf eine Gruppe von Seiten benutzerweise oder rollenweise einzuschränken. Die URL-Autorisierungsregeln werden mithilfe Web.config des <authorization> Elements mit <allow> und <deny> untergeordneten Elementen geschrieben. Zusätzlich zu den in früheren Lernprogrammen erläuterten benutzerbezogenen Autorisierungsregeln kann jedes <allow> und <deny> untergeordnete Element auch Folgendes umfassen:
- Eine bestimmte Rolle
- Eine durch Trennzeichen getrennte Liste von Rollen
Die URL-Autorisierungsregeln gewähren beispielsweise Zugriff auf diese Benutzer in den Rollen "Administratoren" und "Supervisors", verweigern jedoch den Zugriff auf alle anderen Benutzer:
<authorization>
<allow roles="Administrators, Supervisors" />
<deny users="*" />
</authorization>
Das <allow> Element im obigen Markup gibt an, dass die Rollen "Administratoren" und "Supervisors" erlaubt sind; das <deny> Element weist an, dass alle Benutzer verweigert werden.
Konfigurieren wir unsere Anwendung so, dass die Seiten ManageRoles.aspx, UsersAndRoles.aspx und CreateUserWizardWithRoles.aspx nur für Benutzer in der Rolle "Administratoren" zugänglich sind, während die Seite RoleBasedAuthorization.aspx für alle Besucher zugänglich bleibt.
Beginnen Sie dazu mit dem Hinzufügen einer Web.config Datei zum Roles Ordner.
Abbildung 3: Hinzufügen einer Web.config Datei zum Roles Verzeichnis (Klicken, um das Bild in voller Größe anzuzeigen)
Fügen Sie anschließend das folgende Konfigurationsmarkup zu Web.config hinzu:
<?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 der Änderungen bei Web.config an, melden Sie sich als ein Benutzer an, der nicht der Rolle "Administratoren" angehört, und versuchen Sie dann, eine der geschützten Seiten zu besuchen.
UrlAuthorizationModule wird erkennen, dass Sie keine Berechtigung haben, die angeforderte Ressource aufzurufen. Daher leitet er FormsAuthenticationModule Sie zur Anmeldeseite weiter. 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 automatisch alle authentifizierten Benutzer um zu UnauthorizedAccess.aspx, wenn die Abfragezeichenfolge einen ReturnUrl Parameter enthält, da dieser Parameter angibt, dass der Benutzer an die Anmeldeseite gelangt ist, nachdem er versucht hat, eine Seite anzuzeigen, die er nicht berechtigt war anzuzeigen.
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 sich in der Rolle "Administratoren" befindet. Jetzt sollten Sie in der Lage sein, die drei geschützten Seiten anzuzeigen.
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 von oben nach unten einzeln analysiert werden. Sobald eine Übereinstimmung gefunden wird, erhält oder verweigert der Benutzer je nachdem Zugriff, ob die Übereinstimmung in einem <allow>-Element oder einem <deny>-Element gefunden wurde. Wenn keine Übereinstimmung gefunden wird, erhält der Benutzer Zugriff. Wenn Sie daher den Zugriff auf ein oder mehrere Benutzerkonten einschränken möchten, müssen Sie ein <deny> Element als letztes Element in der URL-Autorisierungskonfiguration verwenden. Wenn Ihre URL-Autorisierungsregeln kein <deny>Element enthalten, wird allen Benutzern Zugriff gewährt. Eine ausführlichere Erläuterung dazu, wie die URL-Autorisierungsregeln analysiert werden, finden Sie im Abschnitt „Ein Blick darauf, wie die UrlAuthorizationModule Autorisierungsregeln verwendet werden, um Zugriff zu gewähren oder zu verweigern" des Tutorials User-Based Authorization.
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 welche von der Anzeige einer bestimmten Seite (oder aller Seiten in einem Ordner und seinen Unterordnern) verweigert werden. In bestimmten Fällen möchten wir jedoch möglicherweise allen Benutzern erlauben, eine Seite zu besuchen, aber die Funktionalität der Seite auf der Grundlage der Rollen des Gastbenutzers beschränken. Dies kann das Ein- oder Ausblenden von Daten auf der Grundlage der Rolle des Benutzers oder das Anbieten zusätzlicher Funktionen für Benutzer beinhalten, die zu einer bestimmten Rolle gehören.
Solche feinkörnigen rollenbasierten Autorisierungsregeln können entweder deklarativ oder programmgesteuert implementiert werden (oder durch eine Kombination der beiden). Im nächsten Abschnitt wird gezeigt, wie deklarative Feinkornautorisierung über das LoginView-Steuerelement implementiert wird. Danach werden wir programmatische Techniken untersuchen. Bevor wir uns mit der Anwendung von Feinkornautorisierungsregeln befassen können, müssen wir jedoch zuerst eine Seite erstellen, deren Funktionalität von der Rolle des Benutzers abhängt, der ihn 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 Informationen der einzelnen Benutzer enthält gridView Bearbeitungs- und Löschfunktionen. Zunächst erstellen wir diese Seite mit der Für alle Benutzer verfügbaren Bearbeitungs- und Löschfunktionen. 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 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 Lernprogrammreihe auf Formularauthentifizierung, Autorisierung, Benutzerkonten und Rollen konzentriert, möchte ich nicht zu viel Zeit damit verbringen, die inneren Arbeiten des GridView-Steuerelements zu diskutieren. Dieses Lernprogramm enthält zwar spezifische Schrittweise Anleitungen zum Einrichten dieser Seite, aber es enthält keine Details dazu, warum bestimmte Auswahlmöglichkeiten getroffen wurden oder welche Auswirkungen bestimmte Eigenschaften auf die gerenderte Ausgabe haben. Eine gründliche Untersuchung des GridView-Steuerelements finden Sie in der Lernprogrammreihe "Arbeiten mit Daten" in ASP.NET 2.0 .
Öffnen Sie zunächst die RoleBasedAuthorization.aspx Seite im Roles Ordner. Ziehen Sie ein GridView-Steuerelement von der Seite auf den Designer, und legen Sie es ID fest auf UserGrid. In Kürze werden wir einen Code schreiben, der den Membership aufruft.
GetAllUsers -Methode und bindet das resultierende MembershipUserCollection Objekt an gridView. Das MembershipUserCollection Enthält ein MembershipUser Objekt für jedes Benutzerkonto im System; MembershipUser Objekte weisen Eigenschaften wie UserName,Email,LastLoginDate usw. auf.
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 unteren linken Ecke. Da dieses GridView-Objekt Bearbeitungs- und Löschfunktionen enthalten soll, fügen Sie ein CommandField hinzu, und legen Sie dessen ShowEditButtonShowDeleteButton Eigenschaften auf "True" fest. Fügen Sie als Nächstes vier Felder zum Anzeigen von UserName, Email, und LastLoginDateCommentEigenschaften hinzu. Verwenden Sie ein 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 Eigenschaft UserName anzeigen; setzen Sie dessen HeaderText und DataField Eigenschaften auf "UserName". Dieses Feld kann nicht bearbeitet werden. Legen Sie daher die ReadOnly Eigenschaft auf "True" fest. Konfigurieren Sie das LastLoginDate BoundField, indem Sie dessen HeaderText auf "Last Login" und DataField auf "LastLoginDate" festlegen. Als Nächstes formatieren wir die Ausgabe dieses BoundFields, sodass nur das Datum (anstelle des Datums und der Uhrzeit) angezeigt wird. Legen Sie dazu die Eigenschaft dieses BoundFields HtmlEncode auf False und dessen DataFormatString Eigenschaft auf "{0:d}" fest. Legen Sie auch 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 hier, um das Bild in voller Größe anzuzeigen)
Wir müssen jetzt die ItemTemplate und EditItemTemplate für die "E-Mail" und "Kommentar" Vorlagenfelder definieren. Fügen Sie jedem der ItemTemplates ein Label-Websteuerelement hinzu und binden Sie dessen Text-Eigenschaften an die Email- bzw. Comment-Eigenschaften.
Für das TemplateField "Email" fügen Sie ein TextBox-Objekt hinzu, das Email genannt wird, und binden Sie dessen Eigenschaft Text mit der Eigenschaft Email unter Verwendung einer bidirektionalen Datenbindung. Fügen Sie ein RequiredFieldValidator- und RegularExpressionValidator-Objekt hinzu EditItemTemplate , um sicherzustellen, dass ein Besucher, der die E-Mail-Eigenschaft bearbeitet, eine gültige E-Mail-Adresse eingegeben hat. Fügen Sie für das "Comment" TemplateField ein mehrzeiliges TextBox-Objekt mit dem Namen Comment in sein EditItemTemplate hinzu. Legen Sie die Eigenschaften des TextBox-Steuerelements Columns auf 40 und Rows auf 4 fest, und binden Sie dann die Eigenschaft Text mithilfe von 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 des UserName Benutzers kennen. Legen Sie die Eigenschaft des GridView DataKeyNames auf "UserName" fest, sodass 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 die ShowSummary Eigenschaft auf "False" fest. Mit diesen Einstellungen zeigt die 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, die Gruppe von Benutzerkonten an gridView zu binden. Fügen Sie der Code-Behind-Klasse der Seite RoleBasedAuthorization.aspx eine Methode namens BindUserGrid hinzu, die das von Membership.GetAllUsers zurückgegebene MembershipUserCollection an die UserGrid-GridView bindet. Rufen Sie diese Methode vom Page_Load Ereignishandler beim ersten Seitenbesuch 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
Besuchen Sie mit diesem Code die Seite über einen Browser. Wie in Abbildung 7 dargestellt, sollte ein GridView-Eintrag mit Informationen zu jedem Benutzerkonto im System angezeigt werden.
Abbildung 7: Die UserGrid GridView listet Informationen zu jedem Benutzer im System auf (Klicken, um das Bild in voller Größe anzuzeigen)
Hinweis
Die UserGrid GridView listet alle Benutzer in einer nicht seitenseitigen 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, die 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 und eine zurückgibt, die ganzzahlige Werte für den Seitenindex und die Seitengröße annimmt, und gibt nur die angegebene Teilmenge der Benutzer zurück. Die zweite Überladung kann verwendet werden, um effizienter durch die Benutzerkonten zu blättern, da sie nur die genaue Teilmenge von Benutzerkonten und nicht alle zurückgibt. Wenn Sie Tausende von Benutzerkonten haben, sollten Sie möglicherweise eine filterbasierte Schnittstelle in Betracht ziehen, die nur die Benutzer anzeigt, deren UserName mit einem ausgewählten Zeichen beginnt. Die Membership.FindUsersByName Methode eignet sich ideal zum Erstellen einer filterbasierten Benutzeroberfläche. Wir werden uns mit der Erstellung einer solchen Schnittstelle in einem zukünftigen Lernprogramm befassen.
Das GridView-Steuerelement bietet integrierte Bearbeitungs- und Löschunterstützung, wenn das Steuerelement an ein ordnungsgemäß konfiguriertes Datenquellensteuerelement gebunden ist, z. B. sqlDataSource oder ObjectDataSource. Das UserGrid GridView hat jedoch seine Daten programmgesteuert gebunden. Daher müssen wir Code schreiben, um diese beiden Aufgaben durchzuführen. Insbesondere müssen wir Ereignishandler für die RowEditing, RowCancelingEdit, RowUpdating und RowDeleting-Ereignisse von GridView erstellen, die ausgelöst werden, wenn ein Besucher auf die Bearbeiten-, Abbrechen-, Aktualisieren- oder Löschen-Schaltflächen klickt.
Erstellen Sie zunächst die Ereignishandler für die RowEditing, RowCancelingEdit, und RowUpdating Ereignisse von GridView, und 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 und RowCancelingEdit Ereignishandler setzen einfach die EditIndex-Eigenschaft von GridView und binden dann die Liste der Benutzerkonten erneut an das Grid. Die interessanten Dinge passieren im RowUpdating Ereignishandler. Dieser Ereignishandler beginnt mit der Sicherstellung, dass die Daten gültig sind, und greift dann den UserName Wert des bearbeiteten Benutzerkontos aus der DataKeys Auflistung ab. Auf die Email und Comment TextBoxen in den beiden TemplateFields EditItemTemplate wird dann programmgesteuert 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 Informationen des Benutzers abrufen, die wir über einen Aufruf ausführen Membership.GetUser(userName). Das zurückgegebene MembershipUser-Objekt wird dann aktualisiert, wobei die Email- und Comment-Eigenschaften mit den Werten versehen werden, die in die beiden TextBoxen im Bearbeitungsinterface eingegeben wurden. Schließlich werden diese Änderungen durch einen Aufruf von Membership.UpdateUser gespeichert. Der RowUpdating Ereignishandler wird abgeschlossen, indem die GridView auf die Vorbearbeitungsschnittstelle 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 DataKeys GridView-Auflistung. Dieser UserName Wert wird dann an die DeleteUser Methode der Membership-Klasse ü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 EditIndex auf -1 festgelegt (falls der Benutzer auf "Löschen" geklickt hat, während eine andere Zeile im Bearbeitungsmodus war) und die BindUserGrid Methode aufgerufen wird.
Hinweis
Die Schaltfläche "Löschen" erfordert keine Bestätigung des Benutzers vor dem Löschen des Benutzerkontos. Ich möchte Sie ermutigen, eine Form der Benutzerbestätigung hinzuzufügen, um die Wahrscheinlichkeit zu verkürzen, dass ein Konto versehentlich gelöscht wird. Eine der einfachsten Möglichkeiten, eine Aktion zu bestätigen, besteht in einem clientseitigen Bestätigungsdialogfeld. Weitere Informationen zu dieser Technik finden Sie unter Hinzufügen einer clientseitigen Bestätigung beim Löschen.
Stellen Sie sicher, dass diese Seite erwartungsgemäß funktioniert. Sie sollten in der Lage sein, die E-Mail-Adresse und den Kommentar eines Benutzers zu bearbeiten und jedes Benutzerkonto zu löschen. Da die RoleBasedAuthorization.aspx Seite für alle Benutzer zugänglich ist, können alle Benutzer – auch anonyme Besucher – diese Seite besuchen und Benutzerkonten bearbeiten und löschen! Lassen Sie uns diese Seite aktualisieren, damit nur Benutzer in den Rollen "Supervisors" und "Administratoren" die E-Mail-Adresse und den Kommentar eines Benutzers bearbeiten können, und nur Administratoren können ein Benutzerkonto löschen.
Im Abschnitt "Verwenden des LoginView-Steuerelements" wird die Verwendung des LoginView-Steuerelements untersucht, um Anweisungen anzuzeigen, die für die Rolle des Benutzers spezifisch sind. Wenn eine Person in der Rolle "Administratoren" diese Seite besucht, zeigen wir Anweisungen zum Bearbeiten und Löschen von Benutzern an. Wenn ein Benutzer in der Rolle "Supervisors" diese Seite erreicht, zeigen wir Anweisungen zum Bearbeiten von Benutzern an. Und wenn der Besucher anonym ist oder sich nicht in der Rolle "Vorgesetzte" oder "Administratoren" befindet, wird eine Meldung angezeigt, in der erläutert wird, dass er keine Benutzerkontoinformationen bearbeiten oder löschen kann. Im Abschnitt "Programmgesteuertes Einschränken 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 Lernprogrammen 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 wir ein LoginView-Steuerelement, um unterschiedliche Anweisungen basierend auf der Rolle des Gastbenutzers anzuzeigen.
Fügen Sie zunächst eine LoginView oberhalb der UserGrid GridView hinzu. Wie bereits erwähnt, verfügt das LoginView-Steuerelement über zwei integrierte Vorlagen: AnonymousTemplate und LoggedInTemplate. Geben Sie eine kurze Meldung in beiden Vorlagen 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>
Neben den AnonymousTemplate und LoggedInTemplate kann das LoginView-Steuerelement Rollengruppen beinhalten, die rollenspezifische Vorlagen sind. 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.
Zum Verwalten der RoleGroups klicken Sie im SmartTag des Steuerelements auf den Link "RoleGroups bearbeiten", um den RoleGroup-Sammlungs-Editor anzuzeigen. Fügen Sie zwei neue RoleGroups hinzu. Legen Sie die Eigenschaft der ersten RoleGroup Roles auf "Administratoren" und die der zweiten auf "Vorgesetzte" fest.
Abbildung 8: Verwalten der Role-Specific Vorlagen von LoginView über den RoleGroup-Sammlungs-Editor (Klicken Sie hier, um das 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 aktualisiert, um einen <RoleGroups>-Abschnitt mit einem <asp:RoleGroup>-untergeordneten Element für jede im RoleGroup-Sammlungs-Editor definierte RoleGroup einzuschließen. Darüber hinaus enthält die Dropdownliste "Ansichten" im Smart Tag von LoginView – die zunächst nur AnonymousTemplate und LoggedInTemplate auflistete – nun auch die hinzugefügten RoleGroups.
Bearbeiten Sie die RoleGroups so, dass 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 ähnlich 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 im System angemeldet." Daher können Sie keine Benutzerinformationen bearbeiten oder löschen." Melden Sie sich dann als authentifizierter Benutzer an, aber einer, der sich weder in der Rolle "Supervisors" noch "Administratoren" befindet. Diesmal sollten Sie die Meldung sehen: "Sie sind kein Mitglied der Rollen 'Aufseher' 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 für die Rolle des Aufsehers spezifische Meldung angezeigt werden (siehe Abbildung 9). Und wenn Sie sich als Benutzer in der Rolle "Administratoren" anmelden, sollte die rollenspezifische Meldung "Administratoren" angezeigt werden (siehe Abbildung 10).
Abbildung 9: Die rollenbasierte Nachricht des Supervisors wird Bruce angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 10: Tito wird die rollenspezifische Nachricht des Administratoren angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Wie die Screenshots in Abbildung 9 und 10 zeigen, rendert die LoginView nur eine Vorlage, auch wenn mehrere Vorlagen angewendet werden. Bruce und Tito sind beide angemeldete Benutzer, aber die LoginView rendert nur die übereinstimmende RoleGroup und nicht die LoggedInTemplate. Darüber hinaus gehört Tito zu den Rollen "Administratoren" und "Supervisors", doch das LoginView-Steuerelement rendert die rollenspezifische 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 die LoginView-Vorlage, wenn mehr als eine RoleGroup angegeben ist, die erste RoleGroup rendert, die übereinstimmt. Mit anderen Worten, wenn wir die Supervisors RoleGroup als erste RoleGroup und die Administratoren als zweite platziert hatten, dann, als Tito diese Seite besuchte, würde er die Nachricht "Supervisors" sehen.
Abbildung 11: Der Workflow des LoginView-Steuerelements zum Bestimmen der zu renderenden Vorlage (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Programmgesteuertes Einschränken der Funktionalität
Während das LoginView-Steuerelement unterschiedliche 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 jeden ausblenden, der kein Administrator ist. Um dies zu erreichen, schreiben wir ein wenig Code, der programmgesteuert auf die Edit- und Delete LinkButtons von CommandField verweist, und legt ihre Visible Eigenschaften bei Bedarf auf False.
Die einfachste Möglichkeit zum programmgesteuerten Verweisen auf Steuerelemente in einem CommandField besteht darin, sie zuerst in eine Vorlage zu konvertieren. Klicken Sie hierzu im SmartTag von GridView auf den Link "Spalten bearbeiten", wählen Sie "CommandField" aus der Liste der aktuellen Felder aus, und klicken Sie auf den Link "Dieses Feld in ein TemplateField konvertieren". Dadurch wird das CommandField in ein TemplateField mit einem ItemTemplate und einem EditItemTemplate. Das ItemTemplate enthält die Bearbeiten- und Löschen-LinkButtons, während im EditItemTemplate die Aktualisieren- und Abbrechen-LinkButtons enthalten sind.
Abbildung 12: Konvertieren des CommandField in ein TemplateField (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Aktualisieren Sie die Edit- und Delete LinkButtons im ItemTemplate, und legen Sie deren ID Eigenschaften auf Werte von EditButton bzw DeleteButton.
<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>
Immer wenn Daten an gridView gebunden sind, zählt gridView die Datensätze in ihrer DataSource Eigenschaft auf und generiert ein entsprechendes GridViewRow Objekt. Sobald 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 "Edit" und "Delete LinkButtons" 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
Denken Sie daran, 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 Edit- und Delete LinkButtons 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 durch die If-Anweisung gehandhabt.
Wenn es sich um eine Datenzeile handelt, die sich nicht im Bearbeitungsmodus befindet, werden auf die LinkButton-Objekte "Bearbeiten" und "Löschen" 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 Principal, der von der RoleManagerModule erstellt wurde. Folglich verwendet die IsInRole(roleName)-Methode die Rollen-API, um zu bestimmen, ob der aktuelle Besucher zu roleName gehört.
Hinweis
Wir könnten die Roles-Klasse direkt verwenden und den Aufruf User.IsInRole(roleName) durch einen Aufruf der Methode Roles.IsUserInRole(roleName) ersetzen. Ich habe mich entschieden, die Methode des Hauptobjekts IsInRole(roleName) in diesem Beispiel zu verwenden, da sie effizienter ist, als die Rollen-API direkt zu verwenden. Weiter oben in diesem Lernprogramm haben wir den Rollen-Manager so konfiguriert, dass die Rollen des Benutzers in einem Cookie zwischengespeichert werden. Diese Cache-Cookiedaten werden nur verwendet, wenn die Methode des IsInRole(roleName) Principals aufgerufen wird. Direkte Aufrufe der Rollen-API beinhalten immer eine Abfrage des Rollenspeichers. Auch wenn Rollen nicht in einem Cookie zwischengespeichert werden, ist das Aufrufen der Methode des Principal-Objekts in der Regel effizienter, da die Ergebnisse beim ersten Aufruf während einer Anfrage 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, bedeutet die Nutzung von User.IsInRole(roleName) nur eine Reise zum Rollenspeicher, während Roles.IsUserInRole(roleName)N-Reisen erforderlich sind, wobei N die Anzahl der im GridView angezeigten Benutzerkonten ist.
Die Eigenschaft der Schaltfläche "Bearbeiten" Visible wird auf True festgelegt, wenn sich der Benutzer, der diese Seite besucht, in der Rolle "Administratoren" oder "Supervisors" befindet; andernfalls ist sie auf False gesetzt. Die Eigenschaft der Schaltfläche "Löschen" Visible wird nur dann auf True festgelegt, wenn der Benutzer der Rolle "Administratoren" angehört.
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 Schrägstrich ohne die Schaltflächen "Bearbeiten" oder "Löschen".
Hinweis
Es ist möglich, das CommandField vollständig auszublenden, wenn ein Nicht-Supervisor und kein Administrator die Seite besucht. Ich lasse 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 zur Rolle "Supervisors" gehört (aber nicht der Rolle "Administratoren") besucht, sieht er nur die Schaltfläche "Bearbeiten".
Abbildung 14: Während die Schaltfläche "Bearbeiten" für Supervisors verfügbar ist, ist die Schaltfläche "Löschen" ausgeblendet (Klicken, um das Bild in voller Größe anzuzeigen)
Und wenn ein Administrator besucht, hat sie 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 (Zum Anzeigen des Bilds mit voller Größe klicken)
Schritt 3: Anwenden von rollenbasierten 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 für Administratoren gelöscht. Dies wurde durch Ausblenden der zugehörigen Benutzeroberflächenelemente für nicht autorisierte Benutzer durch programmgesteuerte Techniken erreicht. 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 könnten oder die wir vergessen haben, vor nicht autorisierten Benutzern zu verbergen. Oder ein Hacker kann eine andere Möglichkeit entdecken, um die ASP.NET Seite zum Ausführen der gewünschten Methode zu erhalten.
Eine einfache Möglichkeit, sicherzustellen, dass ein bestimmter Funktionsumfang nicht von einem nicht autorisierten Benutzer aufgerufen werden kann, besteht darin, diese Klasse oder Methode mit dem PrincipalPermission Attribut zu versehen. Wenn die .NET-Laufzeit eine Klasse verwendet oder eine seiner Methoden ausführt, wird überprüft, ob der aktuelle Sicherheitskontext über die Berechtigung 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 Lernprogramm benutzerbasierte Autorisierung angesehen. Insbesondere haben wir gesehen, wie der GridView- SelectedIndexChanged und RowDeleting Ereignishandler so gestaltet werden kann, dass sie nur von authentifizierten Benutzern bzw. Tito ausgeführt werden konnten. Das PrincipalPermission Attribut funktioniert genauso gut mit Rollen.
Lassen Sie uns die Verwendung des PrincipalPermission Attributs in den GridView RowUpdating - und RowDeleting Ereignishandlern veranschaulichen, um die Ausführung für nicht autorisierte Benutzer zu verbieten. 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 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 bestimmt, dass nur Benutzer in den Rollen "Administratoren" oder "Supervisors" den Ereignishandler ausführen können, wobei das Attribut im RowDeleting Ereignishandler die Ausführung auf Benutzer in der Rolle "Administratoren" beschränkt.
Hinweis
Das PrincipalPermission Attribut wird als Klasse im System.Security.Permissions Namespace dargestellt. Achten Sie darauf, dass Sie oben in der CodeBehind-Klassendatei eine Imports System.Security.Permissions Anweisung hinzufügen, um diesen Namespace zu importieren.
Wenn ein Nicht-Administrator irgendwie versucht, den RowDeleting Ereignishandler auszuführen, oder wenn ein Nicht-Supervisor oder Nicht-Administrator versucht, den RowUpdating Ereignishandler auszuführen, wird von der .NET-Laufzeit eine SecurityException ausgelöst.
Abbildung 16: Wenn der Sicherheitskontext nicht zum Ausführen der Methode autorisiert ist, wird ein SecurityException Fehler ausgelöst (Klicken Sie, um das Bild in voller Größe anzuzeigen)
Neben ASP.NET Seiten verfügen viele Anwendungen auch über eine Architektur, die verschiedene Ebenen enthält, z. B. Geschäftslogik und Datenzugriffsebenen. Diese Ebenen werden in der Regel als Klassenbibliotheken implementiert und bieten Klassen und Methoden zum Ausführen von Geschäftslogik- und datenbezogenen Funktionen an. Das PrincipalPermission Attribut ist auch hilfreich, um Autorisierungsregeln auf diese Ebenen anzuwenden.
Weitere Informationen zur Verwendung des PrincipalPermission Attributs zum Definieren von Autorisierungsregeln für Klassen und Methoden finden Sie im Blogeintrag PrincipalPermissionAttributesScott Guthrie.
Zusammenfassung
In diesem Tutorial haben wir uns angesehen, wie grob- und feinkörnige Autorisierungsregeln basierend auf den Rollen des Benutzers angegeben werden. Das URL-Autorisierungsfeature von ASP.NET ermöglicht es einem Seitenentwickler anzugeben, welche Identitäten auf welche Seiten zugelassen oder abgelehnt werden. Wie wir im Benutzerbasierte Autorisierung Tutorial gesehen haben, können URL-Autorisierungsregeln auf Benutzerebene angewendet werden. Sie können auch rollenweise angewendet werden, wie wir in Schritt 1 dieses Lernprogramms gesehen haben.
Feinkornautorisierungsregeln können deklarativ oder programmgesteuert angewendet werden. In Schritt 2 haben wir uns die Verwendung des RoleGroups-Features des LoginView-Steuerelements angesehen, um verschiedene Ausgaben basierend auf den Rollen des Gastbenutzers zu rendern. Außerdem haben wir 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 wird.
Glückliche Programmierung!
Weiterführende Lektüre
Weitere Informationen zu den in diesem Lernprogramm erläuterten Themen finden Sie in den folgenden Ressourcen:
-
Hinzufügen von Autorisierungsregeln zu Geschäfts- und Datenebenen mithilfe von
PrincipalPermissionAttributes - Untersuchung von Mitgliedschaft, Rollen und Profilen in ASP.NET 2.0: Arbeiten mit Rollen
- Sicherheitsfrageliste für ASP.NET 2.0
-
Technische Dokumentation für das
<roleManager>Element
Informationen zum Autor
Scott Mitchell, Autor mehrerer ASP/ASP.NET Bücher und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Scott kann über mitchell@4guysfromrolla.com oder über seinen Blog bei http://ScottOnWriting.NETerreicht werden.
Besonderer Dank an...
Diese Tutorialreihe wurde von vielen hilfreichen Rezensenten überprüft. Die Leitgutachter für dieses Tutorial sind Suchi Banerjee und Teresa Murphy. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn das der Fall ist, schreiben Sie mir eine Nachricht an mitchell@4GuysFromRolla.com