Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Autor : Scott Mitchell
Uwaga / Notatka
Od czasu napisania tego artykułu dostawcy członkostwa ASP.NET zostały zastąpione przez ASP.NET Identity. Zdecydowanie zalecamy aktualizowanie aplikacji w celu korzystania z platformy ASP.NET Identity , a nie dostawców członkostwa proponowanych w czasie pisania tego artykułu. ASP.NET Identity ma wiele zalet w stosunku do systemu członkostwa ASP.NET, w tym :
- Lepsza wydajność
- Ulepszona rozszerzalność i możliwość testowania
- Obsługa uwierzytelniania OAuth, OpenID Connect i uwierzytelniania dwuskładnikowego
- Obsługa tożsamości opartej na oświadczeniach
- Lepsza współdziałanie z platformą ASP.Net Core
Pobierz kod lub pobierz plik PDF
Ten samouczek rozpoczyna się od zapoznania się ze sposobem, w jaki platforma Role kojarzy role użytkownika z jego kontekstem zabezpieczeń. Następnie analizuje sposób stosowania reguł autoryzacji adresów URL opartych na rolach. Następnie przyjrzymy się użyciu środków deklaratywnych i programowych do zmiany wyświetlanych danych i funkcjonalności oferowanych przez stronę ASP.NET.
Introduction
W samouczku dotyczącym User-Based Authorization pokazano, jak używać autoryzacji adresu URL, aby określić, jacy użytkownicy mogą odwiedzać określony zestaw stron. Wystarczy drobne oznaczenie w Web.config, abyśmy mogli zlecić ASP.NET zezwolenie tylko uwierzytelnionym użytkownikom na odwiedzanie strony. Możemy też określić, że tylko użytkownicy Tito i Bob byli dozwoleni lub określić, że wszyscy zautoryzowani użytkownicy z wyjątkiem Sama byli upoważnieni.
Oprócz autoryzacji adresów URL przyjrzeliśmy się również technikom deklaratywnym i programowym kontrolowania wyświetlanych danych oraz funkcjonalności oferowanych przez stronę na podstawie odwiedzania użytkownika. W szczególności utworzyliśmy stronę zawierającą zawartość bieżącego katalogu. Każda osoba może odwiedzić tę stronę, ale tylko uwierzytelnieni użytkownicy mogą wyświetlać zawartość plików i tylko Tito może usunąć pliki.
Stosowanie reguł autoryzacji na zasadzie użytkownik po użytkowniku może stać się koszmarem księgowym. Bardziej przystępnym podejściem jest użycie autoryzacji opartej na rolach. Dobrą wiadomością jest to, że narzędzia do stosowania reguł autoryzacji działają równie dobrze z rolami, jak w przypadku kont użytkowników. Reguły autoryzacji adresów URL mogą określać role zamiast użytkowników. Kontrolka LoginView, która renderuje różne dane wyjściowe dla uwierzytelnionych i anonimowych użytkowników, można skonfigurować tak, aby wyświetlała inną zawartość na podstawie ról zalogowanego użytkownika. Interfejs API Roles zawiera metody określania ról zalogowanego użytkownika.
Ten samouczek rozpoczyna się od zapoznania się ze sposobem, w jaki platforma Role kojarzy role użytkownika z jego kontekstem zabezpieczeń. Następnie analizuje sposób stosowania reguł autoryzacji adresów URL opartych na rolach. Następnie przyjrzymy się użyciu środków deklaratywnych i programowych do zmiany wyświetlanych danych i funkcjonalności oferowanych przez stronę ASP.NET. Zaczynamy!
Opis sposobu, w jaki role są skojarzone z kontekstem zabezpieczeń użytkownika
Za każdym razem, gdy żądanie trafia do potoku ASP.NET, zostaje ono powiązane z kontekstem zabezpieczeń, który zawiera informacje identyfikujące nadawcę żądania. W przypadku korzystania z uwierzytelniania formularzy bilet uwierzytelniania jest używany jako token tożsamości. Jak omówiono w samouczku Omówienie uwierzytelniania formularzy , FormsAuthenticationModule program jest odpowiedzialny za określenie tożsamości osoby żądającej, którą wykonuje podczas AuthenticateRequest zdarzenia.
Jeśli zostanie znaleziony prawidłowy, niewygasły bilet uwierzytelniania, FormsAuthenticationModule dekoduje go w celu ustalenia tożsamości osoby żądającej. Tworzy nowy GenericPrincipal obiekt i przypisuje go do HttpContext.User obiektu. Celem zasobu, takiego jak GenericPrincipal, jest zidentyfikowanie nazwy uwierzytelnionego użytkownika oraz ról, do których ona należy. Ten cel jest widoczny przez fakt, że wszystkie obiekty główne mają Identity właściwość i metodę IsInRole(roleName) . Obiekt FormsAuthenticationModule jednak nie jest zainteresowany rejestrowaniem informacji o roli, a obiekt GenericPrincipal nie określa żadnych ról.
Jeśli framework Ról jest włączony, moduł HTTP RoleManagerModule interweniuje po FormsAuthenticationModule i identyfikuje role uwierzytelnionych użytkowników podczas zdarzenia PostAuthenticateRequest, które jest uruchamiane po zdarzeniu AuthenticateRequest. Jeśli żądanie pochodzi od uwierzytelnionego użytkownika, RoleManagerModule nadpisuje obiekt GenericPrincipal, który został utworzony przez FormsAuthenticationModule, i zastępuje go obiektem RolePrincipal. Klasa RolePrincipal używa interfejsu API ról do określania ról, do których należy użytkownik.
Rysunek 1 przedstawia przepływ pracy potoku ASP.NET podczas korzystania z uwierzytelniania formularzy i frameworku Ról.
FormsAuthenticationModule uruchamia się na początku, identyfikuje użytkownika przy użyciu biletu uwierzytelniania i tworzy nowy obiekt GenericPrincipal. Następnie RoleManagerModule wkracza do akcji i zastępuje obiekt GenericPrincipal obiektem RolePrincipal.
Jeśli anonimowy użytkownik odwiedza witrynę, ani FormsAuthenticationModule ani RoleManagerModule nie tworzą obiektu głównego.
Rysunek 1. Zdarzenia potoku ASP.NET dla uwierzytelnionego użytkownika podczas korzystania z uwierzytelniania formularzy i struktury ról (kliknij, aby wyświetlić obraz pełnowymiarowy)
Buforowanie informacji o roli w pliku cookie
Metoda obiektu RolePrincipal wywołuje IsInRole(roleName)Roles.
GetRolesForUser aby uzyskać role dla użytkownika w celu określenia, czy użytkownik jest członkiem roleName. W przypadku korzystania z elementu SqlRoleProvider powoduje to wysłanie zapytania do bazy danych magazynu ról. W przypadku używania reguł autoryzacji adresów URL opartych na rolach, metoda RolePrincipal's IsInRole będzie wywoływana przy każdym żądaniu do strony chronionej przez te reguły. Zamiast wyszukiwać informacje o rolach w bazie danych na każdym żądaniu, platforma Roles zawiera opcję buforowania ról użytkownika w pliku cookie.
Jeśli struktura ról jest skonfigurowana do buforowania ról użytkownika w pliku cookie, RoleManagerModule tworzy plik cookie podczas zdarzenia potoku ASP.NET EndRequest. Ten plik cookie jest używany w kolejnych żądaniach w PostAuthenticateRequest, co ma miejsce podczas tworzenia obiektu RolePrincipal. Jeśli plik cookie jest prawidłowy i nie wygasł, dane w pliku cookie są analizowane i używane do uzupełniania ról użytkownika, eliminując w ten sposób konieczność wywołania klasy Roles przez RolePrincipal w celu określenia ról użytkownika. Rysunek 2 przedstawia ten przepływ pracy.
Rysunek 2. Informacje o roli użytkownika mogą być przechowywane w pliku cookie w celu zwiększenia wydajności (kliknij, aby wyświetlić obraz pełnowymiarowy)
Domyślnie mechanizm plików cookie pamięci podręcznej dla roli jest wyłączony. Można ją włączyć za pomocą znacznika <roleManager>konfiguracji w pliku Web.config. Omówiliśmy użycie <roleManager> elementu w celu określenia dostawców ról w samouczku Tworzenie ról i zarządzanie nimi , więc ten element powinien już znajdować się w pliku aplikacji Web.config . Ustawienia plików cookie pamięci podręcznej roli są określane jako atrybuty elementu <roleManager>, i są zestawione w tabeli 1.
Uwaga / Notatka
Ustawienia konfiguracji wymienione w tabeli 1 określają właściwości wynikowego pliku cookie pamięci podręcznej roli. Aby uzyskać więcej informacji na temat plików cookie, sposobu ich działania i ich różnych właściwości, przeczytaj ten samouczek dotyczący plików cookie.
| Property | Opis |
|---|---|
cacheRolesInCookie |
Wartość logiczna wskazująca, czy jest używane buforowanie plików cookie. Wartość domyślna to false. |
cookieName |
Nazwa pliku cookie pamięci podręcznej roli. Wartość domyślna to ". ASPXROLES". |
cookiePath |
Ścieżka pliku cookie dla nazwy ról. Atrybut path umożliwia deweloperowi ograniczenie zakresu pliku cookie do określonej hierarchii katalogów. Wartość domyślna to "/", która informuje przeglądarkę, aby wysyłała ciasteczka sesji uwierzytelniania do każdego żądania wysyłanego do domeny. |
cookieProtection |
Wskazuje, jakie techniki są używane do ochrony ciasteczka pamięci podręcznej roli. Dozwolone wartości to: All (wartość domyślna); Encryption; None; i Validation.md) |
|
cookieRequireSSL | Wartość logiczna wskazująca, czy do przesyłania pliku cookie uwierzytelniania jest wymagane połączenie SSL. Wartość domyślna to false cookieSlidingExpiration false createPersistentCookie true cookieTimeout. | | 30 | 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 iscreatePersistentCookie true createPersistentCookie. This value is only pertinent when is set tofalse true. | | | Specifies the time, in minutes, after which the authentication ticket cookie expires. The default value is. This value is only pertinent when cookieTimeoutis set tocookieSlidingExpiration. | | | A Boolean value that specifies whether the role cache cookie is a session cookie or persistent cookie. If(the default), a session cookie is used, which is deleted when the browser is closed. Ifdomain, a persistent cookie is used; it expires number of minutes after it has been created or after the previous visit, depending on the value ofmaxCachedResults RoleManagerModule. | | maxCachedResults| 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 theRolePrincipalattribute, setting it to "yourdomain.com". | | IsInRole | Specifies the maximum number of role names that are cached in the cookie. The default is 25. TheRolesdoes not create a cookie for users that belong to more thanmaxCachedResultsroles. Consequently, theobject'smethod will use theclass to determine the user's roles. The reasonexists 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 wartość; contrariwise, jeśli masz bardzo krótkie nazwy ról, możesz prawdopodobnie zwiększyć tę wartość. |
Tabela 1. Opcje konfiguracji plików cookie cache roli
Skonfigurujmy naszą aplikację tak, aby korzystała z plików cookie do nietrwałego buforowania ról. W tym celu zaktualizuj element <roleManager> w Web.config, aby uwzględnić następujące atrybuty związane z plikami cookie.
<roleManager enabled="true"
defaultProvider="SecurityTutorialsSqlRoleProvider"
cacheRolesInCookie="true"
createPersistentCookie="false"
cookieProtection="All">
<providers>
...
</providers>
</roleManager>
Zaktualizowałem element <roleManager>; dodając trzy atrybuty: cacheRolesInCookie, createPersistentCookiei cookieProtection. Ustawienie cacheRolesInCookie na true spowoduje, że RoleManagerModule będzie teraz automatycznie zapisywać informacje o rolach użytkownika w pliku cookie, zamiast wyszukiwać je przy każdym żądaniu. Jawnie ustawiam atrybut createPersistentCookie na false i atrybut cookieProtection na All, odpowiednio. Technicznie nie musiałem określać wartości dla tych atrybutów, ponieważ właśnie przypisałem je do ich wartości domyślnych, ale umieściłem je tutaj, aby wyraźnie wyjaśnić, że nie używam trwałych plików cookie i że plik cookie jest zarówno zaszyfrowany, jak i zweryfikowany.
To wszystko! W związku z tym struktura Role będzie buforować role użytkowników w plikach cookie. Jeśli przeglądarka użytkownika nie obsługuje plików cookie lub jeśli ich pliki cookie zostaną w jakiś sposób usunięte lub utracone, w jakiś sposób nie jest to wielka sprawa — RolePrincipal obiekt po prostu użyje Roles klasy w przypadku, gdy nie jest dostępny żaden plik cookie (lub nieprawidłowy lub wygasły).
Uwaga / Notatka
Grupa Wzorce i praktyki firmy Microsoft odradza używanie trwałych plików cookie pamięci podręcznej ról. Ponieważ posiadanie ciasteczka pamięci podręcznej roli jest wystarczające do udowodnienia członkostwa w roli, jeśli haker może w jakiś sposób uzyskać dostęp do prawidłowego ciasteczka użytkownika, może podszywać się pod tego użytkownika. Prawdopodobieństwo wystąpienia tego zdarzenia zwiększa się, jeśli plik cookie jest utrwalany w przeglądarce użytkownika. Aby uzyskać więcej informacji na temat tego zalecenia dotyczącego zabezpieczeń, a także innych problemów dotyczących zabezpieczeń, zapoznaj się z listą pytań dotyczących zabezpieczeń dla ASP.NET 2.0.
Krok 1: Definiowanie reguł autoryzacji adresów URL opartych na rolach
Zgodnie z opisem w samouczku User-Based Authorization, autoryzacja adresów URL umożliwia ograniczenie dostępu do zestawu stron na podstawie użytkownika lub roli. Reguły autoryzacji adresu URL są określane w Web.config przy użyciu elementu <authorization> z elementami <allow> i elementami podrzędnymi <deny>. Oprócz reguł autoryzacji związanych z użytkownikiem, omówionych w poprzednich samouczkach, każdy element podrzędny <allow> i <deny> może również obejmować:
- Określona rola
- Rozdzielana przecinkami lista ról
Na przykład reguły autoryzacji adresów URL udzielają dostępu do tych użytkowników w rolach Administratorzy i Nadzorcy, ale odmawiają dostępu wszystkim innym:
<authorization>
<allow roles="Administrators, Supervisors" />
<deny users="*" />
</authorization>
Element <allow> w powyższym znaczniku wskazuje, że role Administratora i Nadzorcy są dozwolone; element <deny> instruuje, że wszyscy użytkownicy są zablokowani.
Skonfigurujmy naszą aplikację tak, aby ManageRoles.aspxstrony , UsersAndRoles.aspxi CreateUserWizardWithRoles.aspx były dostępne tylko dla tych użytkowników w roli Administratorzy, podczas gdy RoleBasedAuthorization.aspx strona pozostaje dostępna dla wszystkich odwiedzających.
Aby to osiągnąć, zacznij od dodania Web.config pliku do Roles folderu.
Rysunek 3. Dodawanie Web.config pliku do Roles katalogu (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Następnie dodaj następujące oznaczenie konfiguracji do: 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>
Element <authorization> w <system.web> sekcji wskazuje, że tylko użytkownicy w roli Administratorzy mogą uzyskiwać dostęp do zasobów ASP.NET w Roles katalogu. Element <location> definiuje alternatywny zestaw reguł autoryzacji adresów URL dla RoleBasedAuthorization.aspx strony, umożliwiając wszystkim użytkownikom odwiedzanie strony.
Po zapisaniu zmian w Web.config, zaloguj się jako użytkownik, który nie ma roli Administratora, a następnie spróbuj odwiedzić jedną z chronionych stron. Program UrlAuthorizationModule wykryje, że nie masz uprawnień do odwiedzenia żądanego zasobu. W związku z tym FormsAuthenticationModule przekierowanie nastąpi do strony logowania. Następnie strona logowania przekierowuje Cię do UnauthorizedAccess.aspx strony (zobacz Rysunek 4). To ostatnie przekierowanie z strony logowania na UnauthorizedAccess.aspx odbywa się z powodu dodanego przez nas kodu na stronie logowania w kroku 2 samouczka "User-Based Authorization". W szczególności strona logowania automatycznie przekierowuje dowolnego uwierzytelnionego użytkownika do UnauthorizedAccess.aspx , jeśli ciąg zapytania zawiera ReturnUrl parametr, ponieważ ten parametr wskazuje, że użytkownik przybył na stronę logowania po próbie wyświetlenia strony, którą nie ma uprawnień do wyświetlania.
Rysunek 4. Tylko użytkownicy w roli Administratorzy mogą wyświetlać chronione strony (kliknij, aby wyświetlić obraz pełnowymiarowy)
Wyloguj się, a następnie zaloguj się jako użytkownik, który jest w roli Administratorzy. Teraz powinno być możliwe wyświetlenie trzech chronionych stron.
Rysunek 5. Tito może odwiedzić UsersAndRoles.aspx stronę, ponieważ jest w roli administratorów (kliknij, aby wyświetlić obraz pełnowymiarowy)
Uwaga / Notatka
Podczas określania reguł autoryzacji adresów URL — dla ról lub użytkowników — należy pamiętać, że reguły są analizowane pojedynczo od góry w dół. Po znalezieniu dopasowania użytkownik otrzymuje lub odmawia dostępu, w zależności od tego, czy dopasowanie zostało znalezione w elemecie <allow> lub <deny> . Jeśli nie zostanie znalezione dopasowanie, użytkownik otrzyma dostęp. W związku z tym, jeśli chcesz ograniczyć dostęp do co najmniej jednego konta użytkownika, konieczne jest użycie <deny> elementu jako ostatniego elementu w konfiguracji autoryzacji adresu URL.
Krok 2. Ograniczanie funkcjonalności na podstawie aktualnie zalogowanych ról użytkownika
Autoryzacja adresu URL ułatwia określenie reguł autoryzacji grubszych, które określają, jakie tożsamości są dozwolone i które z nich są odrzucane podczas przeglądania określonej strony (lub wszystkich stron w folderze i jego podfolderach). Jednak w niektórych przypadkach możemy zezwolić wszystkim użytkownikom na odwiedzanie strony, ale ograniczyć funkcjonalność strony na podstawie ról odwiedzającego użytkownika. Może to oznaczać wyświetlanie lub ukrywanie danych na podstawie roli użytkownika lub oferowanie dodatkowych funkcji użytkownikom należącym do określonej roli.
Takie szczegółowe reguły autoryzacji oparte na rolach można zaimplementować deklaratywnie lub programowo (lub za pomocą kombinacji tych dwóch). W następnej sekcji zobaczymy, jak zaimplementować deklaratywną autoryzację szczegółową za pomocą kontrolki LoginView. Następnie zapoznamy się z technikami programowymi. Zanim jednak będziemy mogli przyjrzeć się zastosowaniu reguł autoryzacji szczegółowej, najpierw musimy utworzyć stronę, której funkcjonalność zależy od roli użytkownika odwiedzającego ją.
Utwórzmy stronę, która wyświetla wszystkie konta użytkowników w systemie za pomocą GridView. Kontrolka GridView będzie zawierać nazwę użytkownika, adres e-mail, datę ostatniego logowania i komentarze dotyczące użytkownika. Oprócz wyświetlania informacji o każdym użytkowniku funkcja GridView będzie zawierać funkcje edytowania i usuwania. Początkowo utworzymy tę stronę z funkcją edycji i usuwania dostępną dla wszystkich użytkowników. W sekcjach "Korzystanie z kontrolki LoginView" i "Programowe ograniczanie funkcjonalności" zobaczymy, jak włączyć lub wyłączyć te funkcje na podstawie roli odwiedzającego użytkownika.
Uwaga / Notatka
Strona ASP.NET, która zostanie skompilowane, używa kontrolki GridView do wyświetlania kont użytkowników. Ponieważ w tej serii samouczków skupiono się na uwierzytelnianiu formularzy, autoryzacji, kontach użytkowników i rolach, nie chcę poświęcać zbyt dużo czasu na omawianie wewnętrznej pracy kontrolki GridView. Chociaż ten samouczek zawiera szczegółowe instrukcje krok po kroku dotyczące konfigurowania tej strony, nie zagłębia się w szczegółowe informacje o tym, dlaczego dokonano pewnych wyborów lub jakie mają wpływ na renderowane dane wyjściowe. Aby zapoznać się z dokładnym badaniem kontrolki GridView, zapoznaj się z serią samouczków Praca z danymi w ASP.NET 2.0 .
Zacznij od otwarcia strony RoleBasedAuthorization.aspx w folderze Roles. Przeciągnij kontrolkę GridView ze strony na projektanta i ustaw jej ID wartość na UserGrid. Za chwilę napiszemy kod, który wywołuje metodę Membership.
GetAllUsers metoda i wiąże wynikowy MembershipUserCollection obiekt z obiektem GridView. Obiekt MembershipUserCollection zawiera MembershipUser obiekt dla każdego konta użytkownika w systemie; MembershipUser obiekty mają właściwości takie jak UserName,EmailLastLoginDate itd.
Zanim napiszemy kod, który wiąże konta użytkowników z siatką, najpierw zdefiniujmy pola obiektu GridView. W tagu inteligentnym gridView kliknij link "Edytuj kolumny", aby uruchomić okno dialogowe Pola (zobacz Rysunek 6). W tym miejscu usuń zaznaczenie pola wyboru "Automatycznie generuj pola" w lewym dolnym rogu. Ponieważ chcemy, aby ten element GridView zawierał możliwości edytowania i usuwania, dodaj pole polecenia i ustaw jego ShowEditButtonShowDeleteButton właściwości na true. Następnie dodaj cztery pola do wyświetlania właściwości UserName, Email, LastLoginDate i Comment. Użyj BoundField dla dwóch właściwości tylko do odczytu (UserName i LastLoginDate) i TemplateFields dla dwóch pól edytowalnych (Email i Comment).
Aby pierwsze pole BoundField wyświetlało właściwość UserName, ustaw właściwości HeaderText i DataField na wartość "UserName". To pole nie będzie edytowalne, więc ustaw jego ReadOnly właściwość na True. Skonfiguruj pole LastLoginDate BoundField, ustawiając dla niego wartość HeaderText "Last Login" i jej DataField wartość "LastLoginDate". Sformatujmy dane wyjściowe tego pola BoundField, aby wyświetlić tylko datę (zamiast daty i godziny). W tym celu ustaw właściwość HtmlEncode tego BoundField na wartość False i właściwość DataFormatString na "{0:d}". Ustaw również właściwość ReadOnly na True.
HeaderText Ustaw właściwości dwóch pól szablonu na "Email" i "Comment".
Rysunek 6. Pola kontrolki GridView można skonfigurować za pomocą okna dialogowego Pola (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Teraz musimy zdefiniować ItemTemplate i EditItemTemplate dla pól szablonów "Email" i "Comment". Dodaj kontrolkę Etykieta Sieć Web do każdej z ItemTemplates i powiąż ich właściwości Text odpowiednio z właściwościami Email i Comment.
Dla pola szablonu "Email" dodaj TextBox o nazwie Email do EditItemTemplate i powiąż jego właściwość Text z właściwością Email przy użyciu dwukierunkowego powiązania danych. Dodaj RequiredFieldValidator i RegularExpressionValidator do EditItemTemplate, aby upewnić się, że gość edytujący właściwość Email wprowadził prawidłowy adres e-mail. W polu TemplateField "Komentarz" dodaj wielowierszowe pole tekstowe o nazwie Comment do elementu EditItemTemplate. Ustaw właściwości TextBox Columns i Rows na 40 i 4, a następnie powiąż właściwość Text do właściwości Comment przy użyciu dwukierunkowego powiązania danych.
Po skonfigurowaniu tych pól szablonów ich deklaratywne znaczniki powinny wyglądać podobnie do następujących:
<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>
Podczas edytowania lub usuwania konta użytkownika musimy znać wartość właściwości tego użytkownika UserName. Ustaw właściwość DataKeyNames elementu GridView na wartość "UserName", aby te informacje były dostępne za pośrednictwem kolekcji DataKeys elementu GridView.
Na koniec dodaj kontrolkę ValidationSummary do strony i ustaw jej ShowMessageBox właściwość na True i jej ShowSummary właściwość na False. Dzięki tym ustawieniom funkcja ValidationSummary wyświetli alert po stronie klienta, jeśli użytkownik spróbuje edytować konto użytkownika z brakującym lub nieprawidłowym adresem e-mail.
<asp:ValidationSummary ID="ValidationSummary1"
runat="server"
ShowMessageBox="True"
ShowSummary="False" />
Teraz ukończyliśmy adiustację deklaratywną tej strony. Następnym zadaniem jest powiązanie zestawu kont użytkowników z kontrolką GridView. Dodaj metodę o nazwie BindUserGrid do klasy code-behind strony, która wiąże dane zwrócone przez Membership.GetAllUsers do kontrolki widoku UserGrid GridView. Wywołaj tę metodę z Page_Load programu obsługi zdarzeń podczas pierwszej wizyty na stronie.
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
Korzystając z tego kodu, odwiedź stronę za pośrednictwem przeglądarki. Jak pokazano na rysunku 7, w systemie powinien zostać wyświetlony widok GridView zawierający informacje o każdym koncie użytkownika.
Rysunek 7. Kontrolka UserGrid GridView wyświetla informacje o każdym użytkowniku w systemie (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Uwaga / Notatka
Obiekt UserGrid GridView wyświetla listę wszystkich użytkowników w interfejsie niestronicowanym. Ten prosty interfejs siatki nie jest odpowiedni w scenariuszach, w których istnieje kilkadziesiąt lub więcej użytkowników. Jedną z opcji jest skonfigurowanie kontrolki GridView w celu włączenia stronicowania. Metoda Membership.GetAllUsers ma dwa przeciążenia: jeden, który nie akceptuje parametrów wejściowych i zwraca wszystkich użytkowników i jeden, który przyjmuje wartości całkowite dla indeksu strony i rozmiar strony, i zwraca tylko określony podzestaw użytkowników. Drugie przeciążenie może służyć do wydajniejszego przeglądania użytkowników, ponieważ zwraca tylko precyzyjny podzbiór kont użytkowników, a nie wszystkich z nich. Jeśli masz tysiące kont użytkowników, możesz rozważyć interfejs oparty na filtrze, który pokazuje tylko tych użytkowników, których nazwa Użytkownika zaczyna się od wybranego znaku, na przykład. Metoda jest idealna Membership.FindUsersByName do tworzenia interfejsu użytkownika opartego na filtrach. Przyjrzymy się tworzeniu takiego interfejsu w przyszłym samouczku.
Kontrolka GridView oferuje wbudowaną obsługę edytowania i usuwania, gdy kontrolka jest powiązana z prawidłowo skonfigurowaną kontrolą źródła danych, taką jak SqlDataSource lub ObjectDataSource. Obiekt UserGrid GridView ma jednak dane powiązane programowo, dlatego musimy napisać kod, aby wykonać te dwa zadania. W szczególności musimy utworzyć programy obsługi dla zdarzeń RowEditing, RowCancelingEdit, RowUpdating i RowDeleting obiektu GridView, które są wyzwalane, gdy odwiedzający kliknie przyciski Edit, Cancel, Update lub Delete.
Zacznij od utworzenia procedur obsługi zdarzeń dla zdarzeń RowEditing, RowCancelingEdit i RowUpdating elementu GridView, a następnie dodaj następujący kod:
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
Procedury obsługi zdarzeń RowEditing i RowCancelingEdit po prostu ustawiają właściwość EditIndex kontrolki GridView, a następnie ponownie powiązują listę kont użytkowników z GridView. Ciekawe rzeczy dzieją się w obsłudze zdarzeń RowUpdating. Ta procedura obsługi zdarzeń rozpoczyna się od upewnienia się, że dane są prawidłowe, a następnie pobiera UserName wartość edytowanego konta użytkownika z DataKeys kolekcji. Pola tekstowe Email i Comment w dwóch TemplateFields EditItemTemplate są następnie przywoływane programowo. Ich Text właściwości zawierają edytowany adres e-mail i komentarz.
Aby zaktualizować konto użytkownika za pomocą interfejsu API członkostwa, musimy najpierw uzyskać informacje użytkownika, które wykonujemy za pośrednictwem wywołania metody Membership.GetUser(userName). Zwrócony obiekt MembershipUser jest następnie aktualizowany, a jego właściwości Email i Comment są uzupełniane wartościami wprowadzonymi do dwóch pól tekstowych z interfejsu edycji. Na koniec te modyfikacje są zapisywane za pomocą wywołania metody Membership.UpdateUser. Procedura RowUpdating obsługi zdarzeń zostanie ukończona, przywracając element GridView do interfejsu wstępnego edytowania.
Następnie utwórz procedurę obsługi zdarzeń RowDeleting RowDeleting, a następnie dodaj następujący kod:
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
Powyższy program obsługi zdarzeń rozpoczyna się od pobrania UserName wartości z kolekcji GridViewDataKeys. Ta UserName wartość jest następnie przekazywana do metody DeleteUser klasy Membership. Metoda DeleteUser usuwa konto użytkownika z systemu, w tym powiązane dane członkostwa (takie jak role, do których należy ten użytkownik). Po usunięciu użytkownika siatka EditIndex jest ustawiona na -1 (w przypadku kliknięcia przez użytkownika przycisku Usuń, gdy inny wiersz był w trybie edycji), a BindUserGrid metoda jest wywoływana.
Uwaga / Notatka
Przycisk Usuń nie wymaga żadnego rodzaju potwierdzenia od użytkownika przed usunięciem konta użytkownika. Zachęcam do dodania jakiejś formy potwierdzenia użytkownika, aby zmniejszyć prawdopodobieństwo przypadkowego usunięcia konta. Jednym z najprostszych sposobów potwierdzenia akcji jest okno dialogowe potwierdzania po stronie klienta. Aby uzyskać więcej informacji na temat tej techniki, zobacz „Dodawanie potwierdzenia po stronie klienta podczas usuwania”.
Sprawdź, czy ta strona działa zgodnie z oczekiwaniami. Możesz edytować adres e-mail i komentarz użytkownika, a także usunąć dowolne konto użytkownika.
RoleBasedAuthorization.aspx Ponieważ strona jest dostępna dla wszystkich użytkowników, każdy użytkownik — nawet użytkownicy anonimowi — mogą odwiedzać tę stronę i edytować i usuwać konta użytkowników. Zaktualizujmy tę stronę, aby tylko użytkownicy w rolach Nadzorcy i Administratorzy mogli edytować adres e-mail i komentarz użytkownika, a tylko administratorzy mogą usunąć konto użytkownika.
Sekcja "Korzystanie z kontrolki LoginView" dotyczy używania kontrolki LoginView w celu wyświetlenia instrukcji specyficznych dla roli użytkownika. Jeśli osoba w roli Administratorzy odwiedza tę stronę, pokażemy instrukcje dotyczące edytowania i usuwania użytkowników. Jeśli użytkownik w roli Nadzorcy osiągnie tę stronę, pokażemy instrukcje dotyczące edytowania użytkowników. Jeśli gość jest anonimowy lub nie znajduje się w roli Nadzorcy lub Administratorzy, zostanie wyświetlony komunikat wyjaśniający, że nie może edytować ani usuwać informacji o koncie użytkownika. W sekcji "Programowe ograniczanie funkcjonalności" napiszemy kod, który programowo pokazuje lub ukrywa przyciski Edytuj i Usuń na podstawie roli użytkownika.
Korzystanie z kontrolki LoginView
Jak widzieliśmy w poprzednich samouczkach, kontrolka LoginView jest przydatna do wyświetlania różnych interfejsów dla uwierzytelnionych i anonimowych użytkowników, ale kontrolka LoginView może być również używana do wyświetlania różnych znaczników na podstawie ról użytkownika. Użyjmy kontrolki LoginView, aby wyświetlić różne instrukcje na podstawie roli odwiedzającego użytkownika.
Zacznij od dodania kontrolki LoginView nad UserGrid GridView. Jak wspomniano wcześniej, kontrolka LoginView ma dwa wbudowane szablony: AnonymousTemplate i LoggedInTemplate. Wprowadź krótki komunikat w obu tych szablonach, który informuje użytkownika, że nie może edytować ani usuwać żadnych informacji o użytkowniku.
<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>
Oprócz kontrolek AnonymousTemplate i LoggedInTemplatekontrolka LoginView może zawierać grupy ról, które są szablonami specyficznymi dla ról. Każda grupa ról zawiera jedną właściwość , która określa, Rolesdo jakich ról ma zastosowanie grupa ról. Właściwość Roles można ustawić na jedną rolę (na przykład "Administratorzy") lub na rozdzielaną przecinkami listę ról (na przykład "Administratorzy, Nadzorcy").
Aby zarządzać RoleGroups, kliknij link "Edytuj RoleGroups" z inteligentnej etykiety kontrolki, aby otworzyć Edytor kolekcji RoleGroup. Dodaj dwie nowe grupy ról. Ustaw właściwość pierwszej GrupyRól Roles na "Administratorzy", a drugiej grupy ról na "Nadzorcy".
Rysunek 8: Zarządzanie szablonami dla określonych ról elementu LoginView za pomocą Edytora Kolekcji RoleGroup (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Kliknij przycisk OK, aby zamknąć Edytor kolekcji RoleGroup; spowoduje to zaktualizowanie deklaratywnego znacznika LoginView, aby uwzględnić sekcję <RoleGroups> z elementem potomnym <asp:RoleGroup> dla każdej grupy ról zdefiniowanej w Edytorze Kolekcji RoleGroup. Ponadto, lista rozwijana "Widoki" w Smart Tagu elementu LoginView, która początkowo zawierała tylko AnonymousTemplate i LoggedInTemplate, teraz również zawiera dodane grupy ról.
Edytuj grupy ról, aby użytkownikom w roli Nadzorcy były wyświetlane instrukcje dotyczące edytowania kont użytkowników, natomiast użytkownikom w roli Administratorzy pokazywane były instrukcje dotyczące edytowania i usuwania. Po wprowadzeniu tych zmian znacznik deklaratywny elementu LoginView powinien wyglądać podobnie do poniższego.
<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>
Po wprowadzeniu tych zmian zapisz stronę, a następnie przejdź do niej za pośrednictwem przeglądarki. Najpierw odwiedź stronę jako użytkownik anonimowy. Powinien zostać wyświetlony komunikat "Nie zalogowano się do systemu. W związku z tym nie można edytować ani usuwać żadnych informacji o użytkowniku". Następnie zaloguj się jako uwierzytelniony użytkownik, ale taki, który nie znajduje się ani w roli Nadzorcy, ani Administratorzy. Tym razem powinien zostać wyświetlony komunikat "Nie jesteś członkiem ról nadzorców ani administratorów. W związku z tym nie można edytować ani usuwać żadnych informacji o użytkowniku".
Następnie zaloguj się jako użytkownik będący członkiem roli Nadzorcy. Tym razem powinien zostać wyświetlony komunikat specyficzny dla ról nadzorców (zobacz Rysunek 9). Jeśli logujesz się jako użytkownik w roli Administratora, powinien się wyświetlić komunikat specyficzny dla roli Administratora (zobacz Rysunek 10).
Rysunek 9: Bruceowi jest wyświetlany komunikat związany z rolą nadzorcy (kliknij, aby wyświetlić obraz pełnowymiarowy)
pl-PL: Rysunek 10: Tito wyświetla komunikat specyficzny dla roli administratora (kliknij, aby wyświetlić obraz pełnowymiarowy)
W miarę wyświetlania zrzutów ekranu na rysunkach 9 i 10 widok LoginView renderuje tylko jeden szablon, nawet jeśli zastosowano wiele szablonów. Bruce i Tito są zalogowanymi użytkownikami, ale LoginView renderuje tylko pasującą LoggedInTemplate RoleGroup, a nie. Ponadto Tito należy zarówno do roli Administratorów, jak i Nadzorców, ale kontrolka LoginView renderuje szablon specyficzny dla roli Administratorów zamiast Nadzorców.
Rysunek 11 ilustruje przepływ pracy używany przez kontrolkę LoginView w celu określenia szablonu do renderowania. Należy pamiętać, że jeśli określona jest więcej niż jedna grupa ról, szablon LoginView renderuje pierwszą grupę ról zgodną z elementem RoleGroup. Innymi słowy, gdybyśmy umieścili RoleGroup nadzorców jako pierwszą grupę, a administratorów jako drugą, to kiedy Tito odwiedzi tę stronę, zobaczy komunikat RoleGroup nadzorców.
Rysunek 11. Przepływ pracy kontrolki LoginView do określania szablonu do renderowania (kliknij, aby wyświetlić obraz pełnowymiarowy)
Programowe ograniczanie funkcjonalności
Kontrolka LoginView wyświetla różne instrukcje na podstawie roli użytkownika odwiedzającego stronę, ale przyciski Edytuj i Anuluj pozostają widoczne dla wszystkich. Musimy programowo ukryć przyciski Edytuj i Usuń dla anonimowych odwiedzających i użytkowników, którzy nie znajdują się ani w roli Nadzorcy, ani Administratorzy. Musimy ukryć przycisk Usuń dla wszystkich, którzy nie są administratorami. Aby to osiągnąć, napiszemy trochę kodu, który programowo odwołuje się do polecenia CommandField's Edit and Delete LinkButtons i ustawia ich Visible właściwości na False, w razie potrzeby.
Najprostszym sposobem programowego odwołowania się do kontrolek w pole polecenia jest najpierw przekonwertowanie go na szablon. Aby to osiągnąć, kliknij link "Edytuj kolumny" z tagu inteligentnego kontrolki GridView, wybierz pole polecenia z listy bieżących pól, a następnie kliknij link "Konwertuj to pole na pole szablonu". To zmienia CommandField w TemplateField z elementem ItemTemplate i EditItemTemplate. Element ItemTemplate zawiera przyciski LinkButton Edycja i Usuń, a EditItemTemplate zawiera przyciski LinkButton Aktualizuj i Anuluj.
Rysunek 12. Konwertowanie pola polecenia na pole szablonu (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Zaktualizuj LinkButtons Edit i Delete w ItemTemplate, ustawiając ich właściwości ID odpowiednio na wartości EditButton i 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>
Za każdym razem, gdy dane są powiązane z kontrolką GridView, funkcja GridView wylicza rekordy we właściwości DataSource i generuje odpowiedni GridViewRow obiekt. Podczas tworzenia każdego obiektu GridViewRow zdarzenie RowCreated jest wyzwalane. Aby ukryć przyciski Edytuj i Usuń dla nieautoryzowanych użytkowników, musimy utworzyć procedurę obsługi zdarzeń dla tego zdarzenia i programowo odwołać się do elementu Edit and Delete LinkButtons, ustawiając odpowiednie Visible właściwości.
Utwórz procedurę obsługi zdarzenia RowCreated, a następnie dodaj następujący kod:
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
Należy pamiętać, że RowCreated zdarzenie jest uruchamiane dla wszystkich wierszy GridView, w tym nagłówka, stopki, interfejsu pager itd. Chcemy w sposób programowy odwoływać się tylko do przycisków Edytuj i Usuń, jeśli chodzi o wiersz danych, który nie jest w trybie edycji (ponieważ wiersz w trybie edycji ma przyciski Aktualizuj i Anuluj zamiast Edytuj i Usuń). Ta kontrola jest obsługiwana przez wyrażenie If.
Jeśli mamy do czynienia z wierszem danych, który nie jest w trybie edycji, LinkButtony Edit i Delete są przywoływane, a ich Visible właściwości są ustawiane na podstawie wartości logicznych zwracanych przez metodę User obiektu IsInRole(roleName). Obiekt User odnosi się do głównego podmiotu utworzonego przez RoleManagerModule; w związku z tym metoda IsInRole(roleName) używa interfejsu API ról do określenia, czy bieżący gość należy do roleName.
Uwaga / Notatka
Moglibyśmy użyć klasy Roles bezpośrednio, zastępując wywołanie User.IsInRole(roleName) wywołaniem metody Roles.IsUserInRole(roleName). Postanowiłem użyć metody głównego obiektu IsInRole(roleName) w tym przykładzie, ponieważ jest bardziej wydajna niż używanie API ról bezpośrednio. Wcześniej w tym samouczku skonfigurowaliśmy menedżera ról do buforowania ról użytkownika w pliku cookie. Buforowane dane plików cookie są używane tylko wtedy, gdy metoda głównego obiektu jest wywoływana; bezpośrednie wywołania interfejsu API ról zawsze obejmują odwołanie do magazynu ról. Nawet jeśli role nie są buforowane w pliku cookie, wywoływanie metody obiektu IsInRole(roleName) głównego jest zwykle bardziej wydajne, ponieważ gdy jest wywoływany po raz pierwszy podczas żądania, buforuje wyniki. Z drugiej strony interfejs API ról nie wykonuje buforowania.
RowCreated Ponieważ zdarzenie jest uruchamiane raz dla każdego wiersza w GridView, użycie User.IsInRole(roleName) obejmuje tylko jeden odczyt z magazynu ról, podczas gdy Roles.IsUserInRole(roleName) wymaga N odczytów, gdzie N jest liczbą kont użytkowników wyświetlanych w GridView.
Właściwość przycisku Edytuj Visible jest ustawiona na True, jeśli użytkownik odwiedzający tę stronę należy do roli Administratorów lub Nadzorców; w przeciwnym razie jest ustawiona na False. Właściwość przycisku Visible Usuń jest ustawiona na True tylko wtedy, gdy użytkownik znajduje się w roli Administrator.
Przetestuj tę stronę za pomocą przeglądarki. Jeśli odwiedzasz stronę jako anonimowy użytkownik lub jako użytkownik, który nie jest ani nadzorcą, ani administratorem, pole CommandField jest puste; nadal istnieje, ale jako wąski pasek bez przycisków „Edytuj” lub „Usuń”.
Uwaga / Notatka
Istnieje możliwość całkowitego ukrycia pola CommandField, gdy stronę odwiedza użytkownik, który nie jest nadzorcą ani administratorem. Zostawię to jako ćwiczenie dla czytelnika.
Rysunek 13. Przyciski edycji i usuwania są ukryte dla osób niebędących nadzorcami i administratorami (kliknij, aby wyświetlić obraz pełnowymiarowy)
Jeśli użytkownik należący do roli Nadzorców (ale nie do roli Administratorów) odwiedza stronę, widzi tylko przycisk Edytuj.
Rysunek 14. Gdy przycisk Edytuj jest dostępny dla nadzorców, przycisk Usuń jest ukryty (kliknij, aby wyświetlić obraz pełnowymiarowy)
A jeśli administrator odwiedza, ma dostęp zarówno do przycisków Edytuj, jak i Usuń.
Rysunek 15. Przyciski Edycji i Usuwania są dostępne tylko dla administratorów (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 3. Stosowanie reguł autoryzacji Role-Based do klas i metod
W kroku 2 ograniczamy możliwości edytowania użytkownikom w rolach Nadzorców i Administratorów oraz usuwamy możliwości tylko dla administratorów. Zostało to osiągnięte przez ukrycie skojarzonych elementów interfejsu użytkownika dla nieautoryzowanych użytkowników za pomocą technik programistycznych. Takie środki nie gwarantują, że nieautoryzowany użytkownik nie będzie mógł wykonać akcji uprzywilejowanej. Mogą istnieć elementy interfejsu użytkownika, które zostały dodane później lub że zapomnieliśmy ukryć dla nieautoryzowanych użytkowników. Lub haker może odkryć inny sposób, aby uzyskać stronę ASP.NET w celu wykonania żądanej metody.
Łatwym sposobem zapewnienia, że nie można uzyskać dostępu do określonego elementu funkcjonalności przez nieautoryzowanego użytkownika, jest dekorowanie tej klasy lub metody za pomocą atrybutuPrincipalPermission . Gdy środowisko uruchomieniowe platformy .NET używa klasy lub wykonuje jedną z jego metod, sprawdza, czy bieżący kontekst zabezpieczeń ma uprawnienia. Atrybut PrincipalPermission udostępnia mechanizm, za pomocą którego można zdefiniować te reguły.
Przyjrzeliśmy się użyciu atrybutu w samouczku dotyczącym autoryzacji opartej na użytkownikach PrincipalPermission. W szczególności zobaczyliśmy, jak udekorować GridViewSelectedIndexChanged i program obsługi zdarzeń RowDeleting, tak aby mogły być uruchamiane tylko przez uwierzytelnionych użytkowników i odpowiednio przez Tito. Atrybut PrincipalPermission działa równie dobrze z rolami.
Pokażmy, jak używać atrybutu PrincipalPermission na gridviewRowUpdating i RowDeleting programach obsługi zdarzeń, aby uniemożliwić wykonywanie nieautoryzowanym użytkownikom. Wszystko, co musimy zrobić, to dodać odpowiedni atrybut na szczycie każdej definicji funkcji:
<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
Atrybut obsługi zdarzeń RowUpdating określa, że tylko użytkownicy w rolach Administratora lub Nadzorcy mogą wykonywać obsługę zdarzeń, podczas gdy atrybut obsługi zdarzeń RowDeleting ogranicza wykonywanie do użytkowników w roli Administratora.
Uwaga / Notatka
Atrybut PrincipalPermission jest reprezentowany jako klasa w System.Security.Permissions przestrzeni nazw. Pamiętaj, aby dodać instrukcję Imports System.Security.Permissions na początku pliku klasy zaplecza kodu, aby zaimportować tę przestrzeń nazw.
Jeśli w jakiś sposób osoba niebędąca administratorem próbuje wykonać procedurę obsługi zdarzeń RowDeleting lub jeśli osoba niebędąca supervisorem lub administratorem próbuje wykonać procedurę obsługi zdarzeń RowUpdating, środowisko uruchomieniowe .NET zwróci wyjątek SecurityException.
Rysunek 16. Jeśli kontekst zabezpieczeń nie ma autoryzacji do wykonania metody, jest SecurityException zgłaszany (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Oprócz ASP.NET stron wiele aplikacji ma również architekturę obejmującą różne warstwy, takie jak logika biznesowa i warstwy dostępu do danych. Te warstwy są zwykle implementowane jako biblioteki klas i oferują klasy i metody do wykonywania funkcji związanych z logiką biznesową i danymi. Atrybut PrincipalPermission jest przydatny do stosowania reguł autoryzacji również do tych warstw.
Aby uzyskać więcej informacji na temat używania atrybutu do definiowania reguł autoryzacji dla klas i metod, zapoznaj się z wpisem PrincipalPermissionscotta Guthrie w blogu Dodawanie reguł autoryzacji do warstw biznesowych i danych przy użyciu polecenia PrincipalPermissionAttributes.
Podsumowanie
W tym samouczku przyjrzeliśmy się sposobom określania reguł autoryzacji gruboziarnistej i szczegółowej na podstawie ról użytkownika. Funkcja autoryzacji adresów URL ASP.NET umożliwia twórcy strony określenie, jakie tożsamości mają dozwolony lub zablokowany dostęp do których stron. Jak widzieliśmy już w samouczku dotyczącym autoryzacji opartej na użytkowniku, reguły autoryzacji adresów URL można stosować indywidualnie dla każdego użytkownika. Można je również stosować indywidualnie dla każdej roli, jak pokazano w kroku 1 tego samouczka.
Reguły szczegółowej autoryzacji mogą być stosowane deklaratywnie lub programowo. W kroku 2 przyjrzeliśmy się funkcji RoleGroups kontrolki LoginView w celu renderowania różnych danych wyjściowych na podstawie ról odwiedzającego użytkownika. Przyjrzeliśmy się również sposobom programowego określania, czy użytkownik należy do określonej roli i jak odpowiednio dostosować funkcjonalność strony.
Szczęśliwe programowanie!
Dalsza lektura
Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:
-
Dodawanie reguł autoryzacji do warstw biznesowych i danych przy użyciu polecenia
PrincipalPermissionAttributes - Badanie członkostwa, ról i profilu ASP.NET 2.0: praca z rolami
- Lista pytań dotyczących zabezpieczeń dla ASP.NET 2.0
-
Dokumentacja techniczna elementu
<roleManager>
Informacje o autorze
Scott Mitchell, autor wielu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Z Scottem można skontaktować się pod mitchell@4guysfromrolla.com lub poprzez jego blog pod adresem http://ScottOnWriting.NET.
Specjalne podziękowania...
Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Główni recenzenci dla tego samouczka to Suchi Banerjee i Teresa Murphy. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, napisz do mnie na adres mitchell@4GuysFromRolla.com