Udostępnij za pośrednictwem


Autoryzacja oparta na rolach (C#)

Autor : Scott Mitchell

Uwaga

Od czasu napisania tego artykułu dostawcy członkostwa ASP.NET zostali zastąpioni przez ASP.NET Identity. Zdecydowanie zalecamy aktualizowanie aplikacji w celu korzystania z platformy ASP.NET Identity , a nie dostawców członkostwa w momencie pisania tego artykułu. ASP.NET Identity ma wiele zalet w porównaniu z systemem 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
  • Lepsze współdziałanie z platformą ASP.Net Core

Pobierz kod lub pobierz plik PDF

Ten samouczek rozpoczyna się od zapoznania się ze sposobem kojarzenia ról 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żywaniu środków deklaratywnych i programowych do zmiany wyświetlanych danych i funkcjonalności oferowanych przez stronę ASP.NET.

Wprowadzenie

W samouczku autoryzacji opartej na użytkownikach pokazano, jak używać autoryzacji adresu URL w celu określenia, co użytkownicy mogą odwiedzać określony zestaw stron. W przypadku niewielkiej ilości znaczników w programie Web.configmożemy poinstruować ASP.NET, aby zezwolić tylko uwierzytelnieni użytkownikom na odwiedzanie strony. Możemy też dyktować, że tylko użytkownicy Tito i Bob byli dozwoloni lub wskazać, że wszyscy uwierzytelnieni użytkownicy z wyjątkiem Sam byli dozwoloni.

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 w oparciu o użytkownika może wzrosnąć do koszmaru księgowania. Bardziej przystępnym podejściem jest użycie autoryzacji opartej na rolach. Dobrą wiadomością jest to, że narzędzia dostępne 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 ról zawiera metody określania ról zalogowanego użytkownika.

Ten samouczek rozpoczyna się od zapoznania się ze sposobem kojarzenia ról 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żywaniu ś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 wprowadza potok ASP.NET jest skojarzony z kontekstem zabezpieczeń, który zawiera informacje identyfikujące osoby żądającej. 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 jest odpowiedzialny za określenie tożsamości osoby żądającej, która odbywa się podczas AuthenticateRequest zdarzenia.

Jeśli zostanie znaleziony prawidłowy, wygasł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 podmiotu zabezpieczeń, takiego jak GenericPrincipal, jest zidentyfikowanie nazwy uwierzytelnionego użytkownika i ról, do których należy. Ten cel jest widoczny przez fakt, że wszystkie obiekty zabezpieczeń mają Identity właściwość i metodę IsInRole(roleName) . Obiekt FormsAuthenticationModule, jednak nie jest zainteresowany rejestrowaniem informacji o roli, a GenericPrincipal tworzony obiekt nie określa żadnych ról.

Jeśli platforma ról jest włączona, RoleManagerModule moduł HTTP krok po i FormsAuthenticationModule identyfikuje uwierzytelnione role użytkownika podczas PostAuthenticateRequest zdarzenia, które jest uruchamiane po AuthenticateRequest zdarzeniu. Jeśli żądanie pochodzi od uwierzytelnionego użytkownika, RoleManagerModule zastępuje GenericPrincipal obiekt utworzony przez FormsAuthenticationModule obiekt i zastępuje go obiektemRolePrincipal . 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 platformy role. Funkcja FormsAuthenticationModule wykonuje najpierw, identyfikuje użytkownika za pośrednictwem biletu uwierzytelniania i tworzy nowy GenericPrincipal obiekt. Następnie kroki opisane w metodzie RoleManagerModule i zastępują GenericPrincipal obiekt obiektem RolePrincipal .

Jeśli anonimowy użytkownik odwiedza witrynę, ani FormsAuthenticationModule obiekt nie RoleManagerModule tworzy obiektu głównego.

Zdarzenia potoku ASP.NET dla uwierzytelnionego użytkownika podczas korzystania z uwierzytelniania formularzy i struktury ról

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)

Metoda RolePrincipal obiektu IsInRole(roleName) wywołuje metodę Roles.GetRolesForUser w celu pobrania ról użytkownika w celu określenia, czy użytkownik jest członkiem role roleName. W przypadku korzystania z SqlRoleProviderprogramu powoduje to wysłanie zapytania do bazy danych magazynu ról. W przypadku korzystania z reguł RolePrincipalautoryzacji adresów URL opartych na rolach metoda będzie wywoływana IsInRole na każdym żądaniu do strony chronionej przez reguły autoryzacji adresów URL oparte na rolach. 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 platforma Role jest skonfigurowana do buforowania ról użytkownika w pliku cookie, RoleManagerModule program tworzy plik cookie podczas zdarzenia potoku EndRequestASP.NET. Ten plik cookie jest używany w kolejnych żądaniach w obiekcie PostAuthenticateRequest, czyli podczas RolePrincipal tworzenia obiektu. Jeśli plik cookie jest prawidłowy i nie wygasł, dane w pliku cookie są analizowane i używane do wypełniania ról użytkownika, co pozwala zaoszczędzić RolePrincipal konieczność wywołania Roles klasy w celu określenia ról użytkownika. Rysunek 2 przedstawia ten przepływ pracy.

Informacje o roli użytkownika mogą być przechowywane w pliku cookie w celu zwiększenia wydajności

Rysunek 2. Informacje o roli użytkownika mogą być przechowywane w pliku cookie w celu zwiększenia wydajności (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Domyślnie mechanizm plików cookie pamięci podręcznej roli jest wyłączony. Można ją włączyć za pomocą <roleManager> znaczników konfiguracji w pliku Web.config. Omówiliśmy używanie <roleManager> elementu do określania dostawców ról w samouczku Tworzenie ról i zarządzanie nimi , więc w pliku aplikacji Web.config powinien już być używany ten element. Ustawienia plików cookie pamięci podręcznej roli są określane jako atrybuty <roleManager> elementu i są sumowane w tabeli 1.

Uwaga

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.

Właściwość Opis
cacheRolesInCookie Wartość logiczna wskazująca, czy buforowanie plików cookie jest używane. Wartość domyślna to false.
cookieName Nazwa pliku cookie pamięci podręcznej roli. Wartość domyślna to ". ASPXROLES".
cookiePath Ścieżka pliku cookie 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ę o wysłaniu pliku cookie biletu uwierzytelniania do dowolnego żądania wysłanego do domeny.
cookieProtection Wskazuje, jakie techniki są używane do ochrony pliku cookie pamięci podręcznej roli. Dozwolone wartości to: All (wartość domyślna); Encryption; None; i Validation.
cookieRequireSSL Wartość logiczna wskazująca, czy do przesyłania pliku cookie uwierzytelniania jest wymagane połączenie SSL. Wartość domyślna to false.
cookieSlidingExpiration Wartość logiczna wskazująca, czy limit czasu pliku cookie jest resetowany za każdym razem, gdy użytkownik odwiedza witrynę podczas jednej sesji. Wartość domyślna to false. Ta wartość jest istotnych tylko wtedy, gdy createPersistentCookie jest ustawiona na truewartość .
cookieTimeout Określa czas (w minutach), po upływie którego wygasa plik cookie biletu uwierzytelniania. Wartość domyślna to 30. Ta wartość jest istotnych tylko wtedy, gdy createPersistentCookie jest ustawiona na truewartość .
createPersistentCookie Wartość logiczna określająca, czy plik cookie pamięci podręcznej roli jest plikiem cookie sesji, czy trwałym plikiem cookie. Jeśli false (ustawienie domyślne), jest używany plik cookie sesji, który jest usuwany po zamknięciu przeglądarki. Jeśli truejest używany trwały plik cookie; wygasa cookieTimeout on kilka minut po utworzeniu lub po poprzedniej wizycie, w zależności od wartości cookieSlidingExpiration.
domain Określa wartość domeny pliku cookie. Wartość domyślna to pusty ciąg, który powoduje, że przeglądarka używa domeny, z której została wystawiona (na przykład www.yourdomain.com). W takim przypadku plik cookie nie zostanie wysłany podczas wysyłania żądań do poddomeny, takich jak admin.yourdomain.com. Jeśli chcesz przekazać plik cookie do wszystkich domen podrzędnych, musisz dostosować domain atrybut, ustawiając go na "yourdomain.com".
maxCachedResults Określa maksymalną liczbę nazw ról, które są buforowane w pliku cookie. Wartość domyślna to 25. Element RoleManagerModule nie tworzy pliku cookie dla użytkowników należących do więcej niż maxCachedResults ról. RolePrincipal W związku z tym metoda obiektu IsInRole będzie używać Roles klasy do określania ról użytkownika. maxCachedResults Przyczyną jest to, że wielu agentów użytkowników nie zezwala na pliki cookie większe niż 4096 bajtów. Dlatego ten limit ma zmniejszyć prawdopodobieństwo przekroczenia tego ograniczenia rozmiaru. Jeśli masz bardzo długie nazwy ról, możesz rozważyć określenie mniejszej maxCachedResults wartości, a w przypadku bardzo krótkich nazw ról możesz prawdopodobnie zwiększyć tę wartość.

Tabela 1: Opcje konfiguracji plików cookie pamięci podręcznej roli

Skonfigurujmy naszą aplikację tak, aby korzystała z plików cookie pamięci podręcznej ról nietrwalnych. Aby to osiągnąć, zaktualizuj <roleManager> element w pliku , Web.config aby uwzględnić następujące atrybuty związane z plikiem cookie:

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

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

Zaktualizowałem <roleManager> element, dodając trzy atrybuty: cacheRolesInCookie, createPersistentCookiei cookieProtection. Ustawienie na truewartość cacheRolesInCookie spowodujeRoleManagerModule, że funkcja automatycznie buforuje role użytkownika w pliku cookie, a nie musi wyszukiwać informacji o roli użytkownika na każdym żądaniu. Jawnie ustawiam createPersistentCookie atrybuty i cookieProtection na false i , Allodpowiednio. Technicznie nie muszę określać wartości dla tych atrybutów, ponieważ właśnie przypisuję je do ich wartości domyślnych, ale umieściłem je tutaj, aby wyraźnie było jasne, ż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 buforuje 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ą 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

Grupa Wzorce & rozwiązania firmy Microsoft odradza używanie trwałych plików cookie pamięci podręcznej ról. Ponieważ posiadanie pliku cookie 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 pliku cookie użytkownika, może personifikować 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 z zabezpieczeniami, zapoznaj się z listą pytań dotyczących zabezpieczeń dla ASP.NET 2.0.

Krok 1. Definiowanie reguł autoryzacji adresów URL Role-Based

Zgodnie z opisem w samouczku autoryzacji opartej na użytkownikach autoryzacja adresów URL umożliwia ograniczenie dostępu do zestawu stron w oparciu o użytkownika lub rolę według roli. Reguły autoryzacji adresów URL są pisane przy Web.config użyciu <authorization> elementu z elementami i <deny> elementami podrzędnymi<allow>. Oprócz reguł autoryzacji związanych z użytkownikiem omówionych w poprzednich samouczkach każdy <allow> element podrzędny <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 do wszystkich innych:

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

Element <allow> w powyższym znaczniku wskazuje, że role Administratorzy i Nadzorcy są dozwolone; <deny> element instruuje, że wszyscy użytkownicy są odrzucani.

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 zrobić, zacznij od dodania Web.config pliku do Roles folderu.

Dodawanie pliku Web.config do katalogu Role

Rysunek 3. Dodawanie Web.config pliku do Roles katalogu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Następnie dodaj następujący znacznik 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 Web.configw programie zaloguj się jako użytkownik, który nie znajduje się w roli Administratorzy, a następnie spróbuj odwiedzić jedną z chronionych stron. Spowoduje UrlAuthorizationModule to wykrycie, że nie masz uprawnień do odwiedzenia żądanego zasobu. W związku z tym FormsAuthenticationModule nastąpi przekierowanie do strony logowania. Następnie strona logowania przekierowuje Cię do UnauthorizedAccess.aspx strony (zobacz Rysunek 4). To ostatnie przekierowanie ze strony logowania do UnauthorizedAccess.aspx wystąpienia z powodu kodu dodanego do strony logowania w kroku 2 samouczka autoryzacji opartej na użytkowniku. W szczególności strona logowania automatycznie przekierowuje dowolnego uwierzytelnionego użytkownika do UnauthorizedAccess.aspx , jeśli zapytanie zawiera ReturnUrl parametr, ponieważ ten parametr wskazuje, że użytkownik przybył na stronę logowania po próbie wyświetlenia strony, która nie została autoryzowana do wyświetlania.

Tylko użytkownicy w roli administratorzy mogą wyświetlać chronione strony

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 znajduje się w roli Administratorzy. Teraz powinno być możliwe wyświetlenie trzech chronionych stron.

Tito może odwiedzić stronę UsersAndRoles.aspx, ponieważ jest w roli administratorów

Rysunek 5. Tito może odwiedzić UsersAndRoles.aspx stronę, ponieważ jest w roli administratorów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

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. Gdy tylko zostanie znalezione dopasowanie, 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. Jeśli reguły autoryzacji adresu URL nie zawierają elementu<deny>element— wszyscy użytkownicy otrzymają dostęp. Aby uzyskać bardziej szczegółową dyskusję na temat analizowania reguł autoryzacji adresów URL, zapoznaj się z sekcją "A Look at UrlAuthorizationModule the How the Authorization Rules to Grant or Deny Access" (Jak używać reguł autoryzacji do udzielania lub odmowy dostępu) w samouczku autoryzacji opartej na użytkowniku.

Krok 2. Ograniczanie funkcjonalności na podstawie aktualnie zalogowanych ról użytkownika

Autoryzacja adresu URL ułatwia określenie reguł autoryzacji coarse, które określają, jakie tożsamości są dozwolone i które z nich są odrzucane podczas wyświetlania 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 wiązać się z wyświetlaniem lub ukrywaniem 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ą jednej kombinacji tych dwóch). W następnej sekcji zobaczymy, jak zaimplementować deklaratywną autoryzację szczegółową za pośrednictwem kontrolki LoginView. Następnie zapoznamy się z technikami programowymi. Zanim jednak będziemy mogli przyjrzeć się zastosowaniu reguł autoryzacji szczegółowości, najpierw musimy utworzyć stronę, której funkcjonalność zależy od roli użytkownika odwiedzającego ją.

Utwórzmy stronę zawierającą listę wszystkich kont użytkowników w systemie w elemecie GridView. Element GridView będzie zawierać nazwę użytkownika, adres e-mail użytkownika, datę ostatniego logowania i komentarze dotyczące użytkownika. Oprócz wyświetlania informacji o każdym użytkowniku funkcja GridView będzie zawierać możliwości 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

Strona ASP.NET, która zostanie skompilowane, używa kontrolki GridView do wyświetlania kont użytkowników. Ponieważ ta seria samouczków koncentruje się na uwierzytelnianiu formularzy, autoryzacji, kontach użytkowników i rolach, nie chcę poświęcać zbyt dużo czasu na omawianie wewnętrznych prac kontrolki GridView. Ten samouczek zawiera szczegółowe instrukcje krok po kroku dotyczące konfigurowania tej strony, ale nie zagłębia się w szczegóły dotyczące tego, dlaczego zostały dokonane pewne wybory, lub jaki wpływ mają określone właściwości na renderowane dane wyjściowe. Aby zapoznać się z dokładnym badaniem kontrolki GridView, zapoznaj się z artykułem Praca z danymi w serii samouczków ASP.NET 2.0 .

Zacznij od otwarcia RoleBasedAuthorization.aspx strony w folderze Roles . Przeciągnij element GridView ze strony na Projektant i ustaw wartość IDUserGrid. W chwili napiszemy kod, który wywołuje metodę Membership.GetAllUsers 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, , EmailLastLoginDatei tak dalej.

Zanim napiszemy kod, który wiąże konta użytkowników z siatką, najpierw zdefiniujmy pola GridView. W tagu inteligentnym elementu 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 wartość True. Następnie dodaj cztery pola do wyświetlania UserNamewłaściwości , Email, LastLoginDatei Comment . Użyj pola 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 pierwszy element BoundField wyświetlił UserName właściwość, ustaw jej HeaderText właściwości 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 wartość HeaderText "Last Login" i jego DataField wartość "LastLoginDate". Sformatujmy dane wyjściowe tego pola Ograniczenia, tak aby wyświetlana jest tylko data (zamiast daty i godziny). Aby to osiągnąć, ustaw właściwość BoundField HtmlEncode na Wartość False, a jej DataFormatString właściwość na "{0:d}". ReadOnly Ustaw również właściwość na true.

HeaderText Ustaw właściwości dwóch pól szablonów na "Email" i "Komentarz".

Pola kontrolki GridView można skonfigurować za pomocą okna dialogowego Pola

Rysunek 6. Pola kontrolki GridView można skonfigurować za pomocą okna dialogowego Pola (kliknij, aby wyświetlić obraz pełnowymiarowy)

Teraz musimy zdefiniować ItemTemplateEditItemTemplate pola szablonów "Email" i "Komentarz". Dodaj kontrolkę Sieć Web Etykieta do każdego elementu ItemTemplate s i powiąż ich Text właściwości odpowiednio z Email właściwościami i Comment .

W przypadku pola szablonu "Email" dodaj pole TextBox o nazwie Email do właściwości EditItemTemplate i powiąż jej Text właściwość z właściwością Email przy użyciu dwukierunkowego powiązania danych. Dodaj element RequiredFieldValidator i RegularExpressionValidator do EditItemTemplate obiektu , aby upewnić się, że gość edytujący właściwość Email wprowadził prawidłowy adres e-mail. W polu TemplateField "Komentarz" dodaj wielowierszowy pole TextBox o nazwie Comment do elementu EditItemTemplate. Ustaw odpowiednio właściwości i pola TextBox Columns na 40 i 4, a następnie powiąż jej Text właściwość z właściwością Comment przy użyciu dwukierunkowego łączenia danych.Rows

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 wiedzieć, że wartość właściwości użytkownika UserName . Ustaw właściwość GridView DataKeyNames na wartość "UserName", aby te informacje są dostępne za pośrednictwem kolekcji GridView DataKeys .

Na koniec dodaj kontrolkę ValidationSummary do strony i ustaw jej ShowMessageBox właściwość na True i jej ShowSummary właściwość na False. W przypadku tych ustawień alert ValidationSummary wyświetli alert po stronie klienta, jeśli użytkownik próbuje edytować konto użytkownika z brakującym lub nieprawidłowym adresem e-mail.

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

Zakończyliśmy deklaratywne narzucie tej strony. Następnym zadaniem jest powiązanie zestawu kont użytkowników z kontrolką GridView. Dodaj metodę o nazwie BindUserGrid do RoleBasedAuthorization.aspx klasy code-behind strony, która wiąże element zwrócony MembershipUserCollection przez Membership.GetAllUsers z kontrolką UserGrid GridView. Wywołaj Page_Load tę metodę z programu obsługi zdarzeń na pierwszej stronie wizyty.

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

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

Po utworzeniu 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.

Kontrolka UserGrid GridView wyświetla informacje o każdym użytkowniku w systemie

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

Kontrolka 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 wydajniejszej strony za pośrednictwem użytkowników, ponieważ zwraca tylko dokładny podzbiór kont użytkowników, a nie wszystkich z nich. Jeśli masz tysiące kont użytkowników, warto 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. Jest Membership.FindUsersByName method to idealne rozwiązanie do tworzenia interfejsu użytkownika opartego na filtrach. W przyszłym samouczku przyjrzymy się tworzeniu takiego interfejsu.

Kontrolka GridView oferuje wbudowaną obsługę edytowania i usuwania, gdy kontrolka jest powiązana z prawidłowo skonfigurowaną kontrolką ź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 należy utworzyć programy obsługi zdarzeń dla zdarzeń, , RowCancelingEditRowUpdatingi RowDeleting zdarzeń GridViewRowEditing, które są uruchamiane po kliknięciu przycisków Edytuj, Anuluj, Aktualizuj lub Usuń obiektu GridView.

Zacznij od utworzenia programów obsługi zdarzeń dla zdarzeń , RowCancelingEditi RowUpdating zdarzeń gridViewRowEditing, a następnie dodaj następujący kod:

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

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

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

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

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

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

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

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

     Membership.UpdateUser(UserInfo);

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

Programy RowEditing obsługi zdarzeń i RowCancelingEdit po prostu ustawić właściwość GridView EditIndex , a następnie ponownie połączyć listę kont użytkowników z siatką. Interesujące rzeczy są wykonywane w procedurze obsługi 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 kolekcji DataKeys . Pola Email tekstowe i Comment w tych dwóch polach TemplateFields EditItemTemplate są następnie programowo przywołyne. 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 o użytkowniku, które wykonujemy za pośrednictwem wywołania metody Membership.GetUser(userName). Zwrócony MembershipUserEmail obiekt i Comment właściwości są następnie aktualizowane przy użyciu wartości wprowadzonych do dwóch pól TextBoxes z interfejsu edycji. Na koniec te modyfikacje są zapisywane za pomocą wywołania metody Membership.UpdateUser. Procedura RowUpdating obsługi zdarzeń zostanie ukończona przez przywrócenie obiektu GridView do interfejsu wstępnego edytowania.

Następnie utwórz procedurę RowDeleting obsługi zdarzeń, a następnie dodaj następujący kod:

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

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

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

Powyższy program obsługi zdarzeń rozpoczyna się od pobrania UserName wartości z kolekcji GridView DataKeys . Ta UserName wartość jest następnie przekazywana DeleteUser do metody 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 (jeśli użytkownik kliknął przycisk Usuń, gdy inny wiersz był w trybie edycji), a BindUserGrid metoda jest wywoływana.

Uwaga

Przycisk Usuń nie wymaga żadnego 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 Client-Side podczas usuwania.

Sprawdź, czy ta strona działa zgodnie z oczekiwaniami. Należy mieć możliwość edytowania adresu e-mail i komentarza użytkownika, a także usuwania dowolnego konta użytkownika. RoleBasedAuthorization.aspx Ponieważ strona jest dostępna dla wszystkich użytkowników, każdy użytkownik — nawet anonimowy odwiedzający — może 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 również służyć 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 użytkownika odwiedzającego.

Zacznij od dodania kontrolki LoginView powyżej kontrolki 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 rozdzielać przecinkami listę ról (na przykład "Administratorzy, Nadzorcy").

Aby zarządzać grupami ról, kliknij link "Edytuj grupy ról" z tagu inteligentnego kontrolki, aby wyświetlić Edytor kolekcji RoleGroup. Dodaj dwie nowe grupy ról. Ustaw właściwość pierwszej grupy ról Roles na "Administratorzy", a druga na "Nadzorcy".

Zarządzanie szablonami Role-Specific elementu LoginView za pomocą edytora kolekcji RoleGroup

Rysunek 8. Zarządzanie szablonami Role-Specific 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 narzutu kontrolki LoginView w celu uwzględnienia <RoleGroups> sekcji z elementem podrzędnym <asp:RoleGroup> dla każdej grupy ról zdefiniowanej w Edytorze kolekcji RoleGroup. Ponadto lista rozwijana "Widoki" na liście inteligentnej elementu LoginView — która początkowo zawierała tylko AnonymousTemplate wartości i LoggedInTemplate — zawiera również dodane grupy ról.

Edytuj grupy ról, aby użytkownicy w roli Nadzorcy wyświetlali instrukcje dotyczące edytowania kont użytkowników, a użytkownicy w roli Administratorzy są wyświetlane 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&#39; Email and Comment information. 
                    Simply click the Edit button, make your changes, and then click Update.
               </ContentTemplate>
          </asp:RoleGroup>
     </RoleGroups>

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

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 logujesz 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 należy ani do roli Nadzorców, ani Administratorów. 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 Administratorzy, powinien zostać wyświetlony komunikat Administratorzy specyficzny dla roli (zobacz Rysunek 10).

Bruce jest pokazany nadzorcy Role-Specific wiadomość

Rysunek 9. Bruce jest wyświetlany nadzorcy Role-Specific komunikat (kliknij, aby wyświetlić obraz pełnowymiarowy)

Tito jest wyświetlane administratorzy Role-Specific komunikat

Rysunek 10. Tito jest wyświetlany administratorom Role-Specific komunikat (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jak pokazano na zrzutach ekranu na rysunkach 9 i 10, kontrolka LoginView renderuje tylko jeden szablon, nawet jeśli zastosowano wiele szablonów. Bruce i Tito są zalogowanymi użytkownikami, ale element LoginView renderuje tylko pasującą grupę LoggedInTemplateRoleGroup, a nie . Ponadto Tito należy zarówno do ról Administratorzy, jak i Nadzorcy, ale kontrolka LoginView renderuje szablon specyficzny dla roli Administratorzy zamiast nadzorców.

Rysunek 11 przedstawia przepływ pracy używany przez kontrolkę LoginView w celu określenia szablonu do renderowania. Należy pamiętać, że jeśli określono więcej niż jedną grupę ról, szablon LoginView renderuje pierwszą grupę ról zgodną z tym elementem. Innymi słowy, gdybyśmy umieścili nadzorców RoleGroup jako pierwszą grupę RoleGroup i administratorów jako drugą, to kiedy Tito odwiedził tę stronę, zobaczy komunikat Nadzorcy.

Przepływ pracy kontrolki LoginView na potrzeby określania szablonu do renderowania

Rysunek 11. Przepływ pracy kontrolki LoginView do określania szablonu do renderowania (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

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 osób odwiedzających i użytkowników, którzy nie mają roli Nadzorcy ani Administratorzy. Musimy ukryć przycisk Usuń dla wszystkich, którzy nie są administratorami. W celu osiągnięcia tego celu napiszemy trochę kodu, który programowo odwołuje się do poleceń CommandField's Edit and Delete LinkButtons i ustawia ich Visible właściwości na false, jeśli to konieczne.

Najprostszym sposobem programowego odwoływanie się do kontrolek w pole polecenia jest najpierw przekonwertowanie jej 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". Spowoduje to zmianę pola commandfield w pole szablonu z elementami i ItemTemplateEditItemTemplate. Zawiera ItemTemplate elementy Edit and Delete LinkButtons, a EditItemTemplate obiekt zawiera kontrolkę Update i Cancel LinkButtons.

Konwertowanie pola polecenia na pole szablonu

Rysunek 12. Konwertowanie pola polecenia na pole szablonu (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Zaktualizuj kontrolkę Edit and Delete LinkButtons w obiekcie ItemTemplate, ustawiając ich ID właściwości 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 obiektem GridView, funkcja GridView wylicza rekordy we właściwości DataSource i generuje odpowiedni GridViewRow obiekt. Po utworzeniu RowCreated każdego GridViewRow obiektu zdarzenie 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 przycisków Edytuj i Usuń LinkButton, ustawiając odpowiednie Visible właściwości.

Utwórz procedurę obsługi zdarzeń, RowCreated a następnie dodaj następujący kod:

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

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

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

Należy pamiętać, że RowCreated zdarzenie jest wyzwalane dla wszystkich wierszy kontrolki GridView, w tym nagłówka, stopki, interfejsu pagera itd. Chcemy programowo odwołać się tylko do przycisków Edytuj i Usuń, jeśli mamy do czynienia z wierszem danych, który nie jest w trybie edycji (ponieważ wiersz w trybie edycji ma przyciski Aktualizuj i Anuluj zamiast Edytuj i Usuń). To sprawdzenie jest obsługiwane przez instrukcję if .

Jeśli mamy do czynienia z wierszem danych, który nie jest w trybie edycji, odwołania do elementów Edit i Delete LinkButton są przywoływane, a ich Visible właściwości są ustawiane na podstawie wartości logicznych zwracanych przez User metodę obiektu IsInRole(roleName) . Obiekt User odwołuje się do podmiotu zabezpieczeń utworzonego RoleManagerModuleprzez element ; w związku z tym metoda używa interfejsu API ról do określenia, IsInRole(roleName) czy bieżący gość należy do roleName.

Uwaga

Moglibyśmy bezpośrednio użyć klasy Roles, zastępując wywołanie metody User.IsInRole(roleName) wywołaniem Roles.IsUserInRole(roleName) metody . Postanowiłem użyć metody obiektu IsInRole(roleName) głównego w tym przykładzie, ponieważ jest ona wydajniejsza niż bezpośrednie użycie interfejsu API ról. Wcześniej w tym samouczku skonfigurowaliśmy menedżera ról do buforowania ról użytkownika w pliku cookie. Te buforowane dane plików cookie są używane tylko wtedy, gdy jest wywoływana IsInRole(roleName) metoda podmiotu zabezpieczeń. Bezpośrednie wywołania interfejsu API ról zawsze obejmują podróż 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ływana 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 siatce, użycie obejmuje User.IsInRole(roleName) tylko jedną podróż do magazynu ról, podczas gdy Roles.IsUserInRole(roleName) wymaga N podróży, gdzie N jest liczbą kont użytkowników wyświetlanych w siatce.

Właściwość przycisku Edytuj jest ustawiona Visible na true wartość , jeśli użytkownik odwiedzający tę stronę znajduje się w roli Administratorzy lub Nadzorcy. W przeciwnym razie jest ustawiona wartość false. Właściwość przycisku Usuń jest ustawiona Visible na wartość tylko wtedy, gdy użytkownik należy do true roli Administratorzy.

Przetestuj tę stronę za pomocą przeglądarki. Jeśli odwiedzasz stronę jako anonimowy gość lub jako użytkownik, który nie jest nadzorcą ani administratorem, pole CommandField jest puste; nadal istnieje, ale jako cienki odcięcie bez przycisków Edytuj lub Usuń.

Uwaga

Istnieje możliwość całkowitego ukrycia pola CommandField, gdy strona jest odwiedzana przez użytkownika niebędącego nadzorcą i nieadministratorem. Zostawię to jako ćwiczenie dla czytelnika.

Przyciski Edytuj i Usuń są ukryte dla osób niebędących nadzorcami i nieadministratorów

Rysunek 13. Przyciski Edytowania i usuwania są ukryte dla osób niebędących nadzorcami i nieadministratorów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jeśli użytkownik należący do roli Nadzorców (ale nie do roli Administratorzy) odwiedza tylko przycisk Edytuj.

Gdy przycisk Edytuj jest dostępny dla nadzorców, przycisk Usuń jest ukryty

Rysunek 14. Gdy przycisk Edytuj jest dostępny dla nadzorców, przycisk Usuń jest ukryty (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Jeśli administrator odwiedzi, ma dostęp zarówno do przycisków Edytuj, jak i Usuń.

Przyciski Edytuj i Usuń są dostępne tylko dla administratorów

Rysunek 15. Przyciski edycji i usuwania są dostępne tylko dla administratorów (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Krok 3. Stosowanie reguł autoryzacji Role-Based do klas i metod

W kroku 2 ograniczamy możliwości edytowania użytkowników w rolach Nadzorców i Administratorów oraz usuwamy możliwości tylko administratorom. Można to osiągnąć, ukrywając skojarzone elementy 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ć się 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 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 jej 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żywaniu atrybutu PrincipalPermission z powrotem w samouczku autoryzacji opartej na użytkownikach. W szczególności zobaczyliśmy, jak ozdobić program obsługi zdarzeń i RowDeleting GridViewSelectedIndexChanged, aby mogły być wykonywane tylko przez uwierzytelnionych użytkowników i Tito, odpowiednio. Atrybut PrincipalPermission działa równie dobrze z rolami.

Pokażmy, jak używać atrybutu PrincipalPermission w programach obsługi zdarzeń i RowDeleting gridviewRowUpdating, aby uniemożliwić wykonywanie nieautoryzowanych użytkowników. 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 void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     ...
}

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

Atrybut programu RowUpdating obsługi zdarzeń określa, że tylko użytkownicy w rolach Administratorzy lub Nadzorcy mogą wykonywać program obsługi zdarzeń, gdzie jako atrybut RowDeleting programu obsługi zdarzeń ogranicza wykonywanie do użytkowników w roli Administratorzy.

Uwaga

Atrybut PrincipalPermission jest reprezentowany jako klasa w System.Security.Permissions przestrzeni nazw. Pamiętaj, aby dodać instrukcję using System.Security.Permissions w górnej części pliku klasy za kodem, aby zaimportować tę przestrzeń nazw.

Jeśli w jakiś sposób nieadministrator próbuje wykonać procedurę RowDeleting obsługi zdarzeń lub jeśli inny niż nadzorca lub inny niż administrator spróbuje wykonać RowUpdating procedurę obsługi zdarzeń, środowisko uruchomieniowe platformy .NET zgłosi błąd SecurityException.

Jeśli kontekst zabezpieczeń nie ma autoryzacji do wykonania metody, zgłaszany jest wyjątek SecurityException

Rysunek 16. Jeśli kontekst zabezpieczeń nie ma autoryzacji do wykonania metody, SecurityException jest zgłaszany (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Oprócz stron ASP.NET 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 przydaje się również do stosowania reguł autoryzacji do tych warstw.

Aby uzyskać więcej informacji na temat używania atrybutu PrincipalPermission do definiowania reguł autoryzacji dla klas i metod, zapoznaj się z wpisem w blogu Scotta GuthrieDodawanie 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. ASP. Funkcja autoryzacji adresów URL platformy NET umożliwia deweloperowi strony określenie, jakie tożsamości są dozwolone lub odmawiane dostępu do jakich stron. Jak już widzieliśmy w samouczku autoryzacji opartej na użytkownikach, reguły autoryzacji adresów URL można stosować dla poszczególnych użytkowników. Można je również stosować w oparciu o rolę, jak pokazano w kroku 1 tego samouczka.

Reguły autoryzacji szczegółowej mogą być stosowane deklaratywnie lub programowo. W kroku 2 przyjrzeliśmy się używaniu funkcji RoleGroups kontrolki LoginView do renderowania różnych danych wyjściowych na podstawie ról użytkownika odwiedzającego. 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!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

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. Scott można dotrzeć pod mitchell@4guysfromrolla.com adresem lub za pośrednictwem swojego bloga pod adresem http://ScottOnWriting.NET.

Specjalne podziękowania...

Ta seria samouczków została przejrzyona przez wielu przydatnych recenzentów. Recenzenci z tego samouczka to Suchi Banerjee i Teresa Murphy. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi linię na mitchell@4GuysFromRolla.com