Rozdział 21.
Zabezpieczanie aplikacji ASP.NET
Zagadnienia związane z bezpieczeństwem aplikacji internetowych są niejednokrotnie trudne zarówno dla programistów jak i użytkowników końcowych; niemniej jednak w dzisiejszych czasach są one niezwykle ważne i nie można ich pomijać. Ogólnie pojęte bezpieczeństwo aplikacji internetowych wiąże się z sprawdzeniem tożsamości użytkownika (uwierzytelnianiem) oraz określeniem jego praw dostępu do zasobów (autoryzacją). W ASP.NET obie te czynności można wykonywać na wiele różnych sposobów, a co najważniejsze, implementacja żadnego z nich nie jest szczególnie trudna.
Technologia ASP.NET sprawia, że zabezpieczanie aplikacji jest całkiem łatwe. Kiedy już zdobędzie się konieczną wiedzę, implementacja odpowiednich mechanizmów zabezpieczających w aplikacji nie przysporzy najmniejszych trudności.
W tym rozdziale zostaną omówione następujące zagadnienia:
Czym jest bezpieczeństwo aplikacji internetowych.
Obsługa mechanizmów zabezpieczeń w systemie Windows.
Trzy różne sposoby uwierzytelniania oraz metody ich implementacji.
Sposoby kontroli dostępu do zasobów serwera.
Czy jest personifikacja oraz jak można z niej korzystać.
Bezpieczeństwo aplikacji internetowych — zagadnienia podstawowe
Przeważająca większość witryn WWW domyślnie zezwala na anonimowy dostęp do swoich zasobów. Oznacza to, że każdy kto dysponuje dostępem do Internetu może wejść na taką witrynę i przejrzeć umieszczone na niej strony WWW. Użytkownicy nie muszą być uwierzytelniani, ich tożsamość nie musi być sprawdzana, a każdy użytkownik dysponuje możliwością obejrzenia dowolnych plików znajdujących się na witrynie. Wyobraźmy sobie jednak, że prowadzimy witrynę, której użytkownicy muszą płacić za możliwość oglądania stron — na przykład, witrynę giełdową udostępniającą profesjonalne analizy i porady. Bez żadnych mechanizmów zabezpieczających każdy mógłby wejść na naszą witrynę i zdobyć bezcenne, publikowane na niej porady i analizy. Bez wątpienia byłoby to klęską dla firmy — po cóż użytkownicy mieliby płacić za prawo dostępu do niej, skoro nie byłoby to konieczne? Mechanizmy bezpieczeństwa aplikacji internetowych mają za zadanie ograniczanie praw dostępu do pewnych plików i udzielanie go wyłącznie określonym grupom użytkowników.
Załóżmy, że pracujemy dla ściśle tajnej agencji rządowej. Do holu budynku może wejść każdy, jednak dalej mogą przejść wyłącznie osoby, których tożsamość została odpowiednio potwierdzona. Otworzenie każdych drzwi w strzeżonym kompleksie, także wymaga potwierdzanie tożsamości, wykonywanego na podstawie analizy siatkówki oka.
Nowe wyrażenie
Powyższy proces przedstawia podstawowy sposób działania mechanizmów zabezpieczający stosowanych na WWW. Pierwszym krokiem jest uwierzytelnienie — czyli proces określenia tożsamości użytkownika żądającego dostępu do informacji. Tożsamość użytkowników określana jest na podstawie odpowiednich informacji uwierzytelniających, które mogą przyjmować bardzo różne postaci (najczęściej jest to nazwa użytkownika oraz hasło). Dzięki uwierzytelnianiu można uzyskać pewność, że użytkownik który przesłał żądanie jest tym, za kogo się podaje. Jeśli system zabezpieczeń nie będzie w stanie określić tożsamości użytkownika na podstawie przesłanych informacji uwierzytelniających, to proces uwierzytelniania nie zostanie wykonany poprawnie, a anonimowy użytkownik nie uzyska dostępu do zasobów. Jeśli jednak informacje uwierzytelniające okażą się poprawne, to użytkownik uzyska dostęp do systemu i zostanie mu przydzielona odpowiednia „tożsamość”.
Nowe wyrażenie
Po określeniu tożsamości użytkownika, system sprawdza do jakich zasobów może on uzyskać dostęp. Proces ten nazywany jest autoryzacją. Kontynuując przykład tajnej agencji rządowej, można założyć, że niektóre drzwi mogą otwierać wyłącznie osoby dysponujące odpowiednimi prawami dostępu. System określa je na podstawie uprawnień nadanych konkretnej tożsamości (czyli konkretnemu użytkownikowi). Dzięki temu pracownik agencji może dysponować prawem otwierania pewnych drzwi, jednak inne pozostaną dla niego niedostępne. W przypadku WWW oznacza to, że to od tożsamości użytkownika będzie zależało do jakich plików będzie on miał dostęp.
Nowe wyrażenie
W końcu ostatnim etapem, jest personifikacja. System zabezpieczający budynku agencji rządowej można sobie wyobrazić jako strażnika. Ma on dostęp do każdego pomieszczenia w budynku i może otwierać wszystkie znajdujące się w nim drzwi, a to wszystko bez konieczności wykonywania analizy siatkówki. A teraz wyobraźmy sobie, że jakiś chytry i inteligentny szpieg włamał się do tego systemu. Osoba taka uzyskałaby dostęp do wszystkich pomieszczeń w budynku, a system bezpieczeństwa nie spełniłby swego zadania.
Jako dodatkowy środek zabezpieczający projektanci systemu zabezpieczającego wprowadzili mechanizm personifikacji. Gdy jakaś osoba próbuje wejść do budynku lub użyć którego z zainstalowanych w nim komputerów, strażnik personifikuje tę osobę (czyli zaczyna ją „udawać”) ograniczając tym samym swoje własne uprawnienia.
Innymi słowy strażnik chętnie rezygnuje ze swych własnych możliwości, aby włamywacz nie mógł ich wykorzystać. Można by to porównać od generała, który zażywa jakieś tajemnicze pigułki dzięki której może zapomnieć wszystkie kluczowe informacje w razie gdyby został schwytany przez nieprzyjaciół. Być może pojęcia te wydają się nieco abstrakcyjne, jednak staną się znacznie bardziej zrozumiałe, gdy wykorzystanym je przy tworzeniu i zabezpieczaniu stron ASP.NET. Na rysunku 21.1 został przedstawiony proces, jaki przechodzi użytkownik aby uzyskać dostęp do zasobów systemowych.
Rysunek 21.1. Typowy protokół bezpieczeństwa
Opis rysunku
Supply… — Podanie danych uwierzytelniających użytkownika
Authenticated? — Uwierzytelniony?
Yes — Tak
No — Nie
Try to … — Próba uzyskania dostępu do zasobów
Authorized? — Autoryzowany?
Impersonate … — Personalizacja danej tożsamości
Ogólnie rzecz biorąc mechanizmy zabezpieczeń w ASP.NET są implementowane przy wykorzystaniu dwóch różnych metod. Można uwierzytelniać i autoryzować użytkowników przy wykorzystaniu kont użytkowników systemu operacyjnego (za pośrednictwem możliwości serwera IIS) lub też można porównywać dane użytkownika z prawami dostępu określonymi w źródłach danych (na przykład, za pomocą plików konfiguracyjnych web.config). Wykorzystanie pierwszej z tych metod wymaga bardzo niewielkiej pracy i wprowadzenia jedynie nieznacznych modyfikacji w kodzie stron ASP.NET. Jednak z drugiej strony, metoda ta daje mniejszą kontrolę nad przebiegiem procesu uwierzytelniania. Z kolei druga metoda jest przeciwieństwem pierwszej — wymaga znacznego wkładu pracy lecz daje znacznie większe i bardziej elastyczne możliwości. Obie te metody zostaną szczegółowo omówione w dalszej części rozdziału.
Zabezpieczenie w systemie Windows
Nowe wyrażenie
System operacyjny Windows dysponuje mechanizmami zabezpieczeń bazującymi na „rolach”. Rola określa typ tożsamości. Na przykład, jeśli jesteś sprawujesz pieczę nad systemem komputerowym firmy oraz odpowiadasz za instalację sprzętu i oprogramowania, to znaczy że działasz w roli administratora. Jeśli ktoś będzie jedynie chciał przejrzeć jakieś strony WWW, to będzie „występował w roli” gościa (gościa w odniesieniu do zasobów komputera). Role określają w jakim stopniu dana tożsamość może kontrolować komputer oraz jakimi uprawnieniami dysponuje.
Zazwyczaj z rolami jest skojarzonych kilka tożsamości. Na przykład, Twoim komputerem może się opiekować kilka osób, czyli może być kilku administratorów. Może także Ty jesteś jednym z nich? W systemie Windows te tożsamości są określane jako użytkownicy.
Przyjrzyjmy się użytkownikom dostępnym na Twoim komputerze. W systemie Windows 2000 kliknij przycisk Start i wybierz z menu opcję --> ProgramyNarzędzia administracyjneZarządzanie komputerem. W wyświetlonym oknie, na hierarchicznej liście wyświetlonej z jego lewej strony zaznacz opcję Narzędzia systemoweUżytkownicy i grupy lokalneUżytkownicy[Author:p8R] (patrz rysunek 21.2). Na ekranie powinno się pojawić okno podobne do tego, przedstawionego na rysunku 21.2.
Rysunek 21.2. Lista użytkowników w systemie Windows 2000.
Jak widać na powyższym rysunku, w prawej części okna została wyświetlona lista wszystkich użytkowników zdefiniowanych w systemie. Być może zauważysz na niej kilku, o których istnieniu nic nie wiedziałeś! Aby wyświetlić listę wszystkich zdefiniowanych w systemie grup, należy kliknąć opcję Użytkownicy i grupy lokalneGrupy z lewej strony okna Zarządzanie komputerem. Jeśli chcesz sprawdzić jacy użytkownicy należą do jakiejś grupy, kliknij ją dwa razy — w wyświetlony oknie dialogowym pojawi się lista wszystkich użytkowników należących do danej grupy.
Podpowiedź
Jedną z często stosowanych i łatwych metod zabezpieczania jest usunięcie wszystkich nieznanych użytkowników wyświetlonych na rysunku 21.2. Należy jednak zachować dużą ostrożność, aby nie usunąć własnego użytkownika ani żadnego z użytkowników systemowych.
Przewiń listę ku dołowi, aż pojawi się na niej użytkownik o nazwie IUSR_NazwaKomputera. To domyślna tożsamość z której będą korzystali użytkownicy używający danego komputera za pośrednictwem lokalnego serwera WWW. Jest to konto anonimowe, co oznacza, że aby wykorzystać go do uzyskania dostępu do zasobów komputera, nie trzeba podawać żadnego hasła. Z tego powodu domyślne uprawnienia jakimi dysponuje ta tożsamość są minimalne.
Zwróć uwagę, iż w tym miejscu nie można określać praw dostępu jakimi będzie dysponować dana tożsamość. Więcej informacji na ten temat zostanie podanych w dalszej części rozdziału, pt.: „Autoryzacja”.
Uwierzytelnianie
W technologii ASP.NET uwierzytelnianie jest implementowane za pośrednictwem tak zwanych dostawców uwierzytelnień (ang.: authentication providers), czyli modułów zawierających kod służący do uwierzytelniania żądań przesyłanych przez klienty WWW. Działanie tych modułów jest kontrolowane za pośrednictwem plików konfiguracyjnych web.config, a konkretnie za pomocą umieszczanych w nich znaczników authentication. Podstawowy sposób zapisu tych znaczników został przedstawiony na poniższym przykładzie:
<configuration>
<system.web>
<authentication mode="tryb">
</authentication>
</system.web>
</configuration>
Wewnątrz znaczników authentication można dodatkowo umieścić elementy form oraz credentials. Więcej informacji na ich temat znajdziesz w dalszej części rozdziału, pt.: „Uwierzytelnianie za pośrednictwem formularza”.
Ostrzeżenie
Znacznik authentication można stosować wyłącznie w pliku web.config umieszczonym na głównym poziomie witryny. Próba użycia tego znacznika w plikach web.config umieszczonych w jakimkolwiek innym folderze witryny zakończy się zgłoszeniem błędu.
Technologia ASP.NET udostępnia trzy metody (zwane także modelami) uwierzytelniania użytkowników — uwierzytelnianie systemu Windows, uwierzytelnianie przy wykorzystaniu usługi Passport oraz uwierzytelnianie za pośrednictwem formularzy. Każda z nich została zaimplementowana przez innego dostawcę uwierzytelnień. Pierwsza z tych metod jest realizowana przy wykorzystaniu serwera IIS i nie wymaga żadnych (lub bardzo niewielkich) modyfikacji w tworzonych stronach ASP.NET. Pozostałe dwie metody — uwierzytelnianie za pośrednictwem formularzy oraz uwierzytelnianie przy użyciu usługi Passport — są bardzo podobne. Pierwsza z nich jest implementowana na serwerze na jakim działa aplikacja, a druga jako płatna usługa świadczona przez firmę Microsoft. Wszystkie te trzy metody zostaną szczegółowo omówione w kolejnych częściach rozdziału.
Uwierzytelnianie systemu Windows
Gdy klient przesyła żądanie dotyczące jakiejś strony ASP.NET w pierwszej kolejności jest ono odbierane przez serwer WWW, a konkretnie — Internet Information Server (IIS). Po odebraniu żądania serwer IIS może uwierzytelnić użytkownika bądź pozostawić przeprowadzenie uwierzytelnienia w gestii aplikacji ASP.NET. Jeśli to serwer będzie uwierzytelniał użytkownika, to jest on w stanie porównać jego dane uwierzytelniające bezpośrednio z informacjami jakimi dysponuje system operacyjny (Windows 2000 lub Windows NT). Schemat uwierzytelnienia wykonywanego przez IIS został przedstawiony na rysunku 21.3.
Rysunek 21.3. Schemat zabezpieczeń ASP.NET
Opis rysunku
Client — Klient
Browser — Przeglądarka
Request — Żądanie
Server — Serwer
IIS — IIS
ASP.NET - ASP.NET
.NET Framework - Środowisko .NET
Windows NT/2000 - Windows NT/2000
Notatka
Serwer IIS nie wymaga przeprowadzania uwierzytelniania. Serwer może przekazywać wszystkie odbierane żądania bezpośrednio do aplikacji, co sprawi, że to strony ASP.NET będą odpowiedzialne za uwierzytelnienie użytkownika. Wszyscy użytkownicy, którym IIS pozwala na dostęp do zasobów serwera bez potwierdzenia ich tożsamości, określani są jako użytkownicy anonimowi.
Tożsamości wykorzystywane przez IIS są określane przez konta użytkowników systemu Windows. To właśnie z tego powodu ten sposób uwierzytelniania określany jest jako uwierzytelnianie systemu Windows. Te konta użytkowników systemu Windows przypominają nieco role przedstawione na rysunku 21.2. W tym przypadku klienci WWW dysponują takimi samymi uprawnieniami co użytkownicy i role systemu Windows. Na przykład, jeśli klient pełni rolę administratora, to będzie on miał prawo wprowadzania dowolnych modyfikacji w systemie plików, czyli także do usuwania i przenoszenia plików.
Aby wykorzystać ten sposób uwierzytelniania, należy umieścić poniższy znacznik w pliku konfiguracyjnym web.config:
<authentication mode="Windows" />
Serwer IIS używa trzech różnych typów uwierzytelniania systemu Windows — podstawowego (Basic), bazującego na skrótach (Digest) oraz NTLM (określanego także jako zintegrowane uwierzytelnianie Windows, ang: Integrated Windows Authentication). Zobaczmy teraz jak działa każdy z tych trzech typów uwierzytelniania systemu Windows oraz jak można go zaimplementować w aplikacjach ASP.NET.
Uwierzytelnianie podstawowe (Basic) jest najprostszą metodą uwierzytelniania. Jej możliwości są tak ograniczone iż, na dobrą sprawę, nie różni się ona od braku wykorzystania jakichkolwiek mechanizmów uwierzytelniających. Być może, odwiedzając witryny WWW, spotkałeś się już z tą metodą uwierzytelniania. Jest ona bowiem standardowym sposobem pobierania danych uwierzytelniających do użytkowników i stanowi element specyfikacji protokołu HTTP opracowanej przez konsorcjum W3C. Poniżej został opisany przebieg uwierzytelniania podstawowego:
Klient przesyła na serwer żądanie dotyczące chronionego zasobu.
Serwer WWW przesyła odpowiedź zawierającą nagłówek 401 Unauthorized.
Przeglądarka WWW odbiera tę odpowiedź i prosi użytkownika o podanie danych uwierzytelniających — zazwyczaj jest to nazwa użytkownika i hasło.
Przeglądarka ponownie próbuje uzyskać dostęp do zasobu serwer posługując się przy tym podanymi przez użytkownika danymi uwierzytelniającymi.
Jeśli dane uwierzytelniające nie są poprawne, to cały proces rozpoczyna się ponownie od etapu 2.
Jeśli uda się potwierdzić tożsamość użytkownika, przeglądarka uzyskuje dostęp do żądanego zasobu (lub zasobów).
A zatem zabezpieczmy coś! Pierwszym krokiem będzie uruchomienie Menedżera usług internetowych. W tym celu kliknij przycisk Start i wybierz opcję UstawieniaPanel sterowania; w wyświetlonym oknie dwukrotnie kliknij ikonę Narzędzia administracyjne, a w kolejnym oknie — ikonę Menedżer usług internetowych. W wyświetlonym oknie Internet Information Services rozwiń hierarchiczną listę wyświetloną z jego lewej strony i zaznacz opcje Domyślna witryna sieci Web. Teraz wybierz folder (lub katalog wirtualny) który chcesz zabezpieczyć (my zabezpieczymy folder /aspnetdlakazdego/rozdzial21; jeśli to konieczne to stwórz go w folderze c:\inetpub\wwwroot). Teraz kliknij wybrany folder prawym przyciskiem myszy i z menu kontekstowego wybierz opcję Właściwości (patrz rysunek 21.4.).
Rysunek 21.4. Wyświetlanie właściwości folderu w Menadżerze usług internetowych
W wyświetlonym oknie dialogowym, na zakładce Katalog, zaznacz pole wyboru Przeglądanie katalogów; dzięki temu będziemy wiedzieć kiedy proces uwierzytelnienia użytkownika zakończył się pomyślnie. Następnie przejdź na zakładkę Zabezpieczenia katalogów i kliknij przycisk Edytuj w sekcji Dostęp anonimowy i kontrola uwierzytelnienia. Na ekranie powinno się pojawić okno dialogowe przedstawione na rysunku 21.5.
Rysunek 21.5. Określanie właściwości uwierzytelniania
Jeśli jest zaznaczone pole wyboru Dostęp anonimowy, to usuń z niego znacznik. Dostęp anonimowy sprawia, że każdy użytkownik ma prawo pobrać dowolne zasoby znajdujące się w danym katalogu, a w przypadku naszej aplikacji nie chcemy aby było to możliwe. Następnie zaznacz pole wyboru Uwierzytelnienie podstawowe (i usuń znacznik z pola Zintegrowane uwierzytelnienie systemu Windows).
Po zmodyfikowaniu ustawień zamknij oba okna dialogowe klikając przycisk OK w każdym z nich. Teraz wpisz w przeglądarce następujący adres URL:
http://localhost/aspnetdlakazdego/rozdzial21
Na ekranie powinno się pojawić okienko dialogowe przedstawione na rysunku 21.6; należy w nim podać informacje, które zostaną użyte do uwierzytelnienia użytkownika.
Rysunek 21.6. Po włączeniu uwierzytelniania podstawowego przeglądarka prosi o podanie informacji o użytkowniku
W powyższym okienku dialogowym wpisz informacje o dowolnym koncie użytkownika zdefiniowanym na lokalnym komputerze (na przykład od koncie którego używasz aby zalogować się na ten komputer). IIS porówna podane informacje z listą użytkowników systemu operacyjnego i uwierzytelni lub odrzuci żądanie. Jeśli poprawność podanych informacji zostanie potwierdzona, to w przeglądarce powinna pojawić się strona przedstawiona na rysunku 21.7.
Rysunek 21.7. Po uwierzytelnieniu użytkownika zostaje wyświetlona strona z zawartością folderu
Notatka
Po pomyślnie wykonanym uwierzytelnieniu użytkownika, aby skorzystać z innego użytkownika i hasła, będziesz musiał ponownie uruchomić przeglądarkę, zażądać strony i podać nowe dane uwierzytelniające. Przeglądarka zapamiętuje bowiem te informacje i używa ich aż do momentu zamknięcia programu. Oznacza to, że otworzenie nowego, kolejnego okna przeglądarki nie wystarczy jeśli chcesz podać nowe dane uwierzytelniające.
W przypadku uwierzytelniania podstawowego nazwa użytkownika oraz hasła wpisywane w okienku dialogowym przedstawionym na rysunku 21.6. są przesyłane na serwer w postaci zwyczajnego tekstu. To efektywny lecz niezbyt bezpieczny sposób przeprowadzania uwierzytelniania. Inteligentny hacker może przejąć wiadomość nim ta dotrze na serwer i wykorzystać zapisane w niej informacje, aby uzyskać dostęp do systemu.
Uwierzytelnianie bazujące na skrótach działa podobnie jak uwierzytelnianie podstawowe, z tym że zarówno nazwa użytkownika jak i hasło są szyfrowane przed wysłaniem. Wykorzystywany algorytm szyfrujący, nazywany funkcją skrótu, modyfikuje informacje w taki sposób iż nie można ich odszyfrować. Proces ten jest wyłącznie jednokierunkowy:
Klient żąda dostępu do chronionego zasobu, a serwer przesyła w odpowiedzi prośbę o uwierzytelnienie.
Serwer przesyła odpowiedź o "401 Unauthorized".
Przeglądarka WWW odbiera tę odpowiedź i prosi użytkownika o podanie danych uwierzytelniających. Następnie przeglądarka dodaje do nich nieco całkowicie losowych informacji i szyfruje je. Dzięki tym unikalnym informacjom można zapewnić, że nikt nie będzie w stanie skopiować kodu skrótu i wykorzystać go do uzyskania dostępu do systemu w późniejszym czasie.
Przeglądarka przesyła na serwer zaszyfrowane informacje uwierzytelniające oraz niezaszyfrowaną kopię dodatkowych informacji. Serwer wykorzystuje te dodatkowe informacje do zaszyfrowania posiadanych przez niego danych uwierzytelniających (czyli informacji o użytkowniku systemu Windows).
Serwer porównuje utworzone przez siebie zaszyfrowane dane uwierzytelniające z danymi przesłanymi przez przeglądarkę.
Jeśli obie porównywane informacje nie są identyczne, żądanie nie zostaje uwierzytelnione i cały proces rozpoczyna się ponownie od punktu 3.
W przypadku poprawnego uwierzytelnienia żądania przeglądarka uzyskuje dostęp do odpowiedniego zasobu.
Aby umożliwić wykorzystanie tej metody uwierzytelniania należy zaznaczyć pole wyboru Uwierzytelnienie skrócone dla serwerów domeny systemu Windows (patrz rysunek 21.5) (należy zwrócić uwagę, iż opcja ta jest dostępna wyłącznie wtedy, gdy serwer będzie podłączony do domeny). Dodatkowo należy się upewnić, że nie jest zaznaczone pole wyboru Dostęp anonimowy.
I w końcu, w przypadku zastosowania ostatniej metody uwierzytelniania — NTLM — nigdy nie jest wyświetlane żadne okienko dialogowe, w którym użytkownik mógłby podać dane uwierzytelniające. Nie jest to konieczne, gdyż gdy tylko przeglądarka nawiąże kontakt z serwerem przesyła do niego zaszyfrowane informacje, które użytkownik podał przy logowaniu się do systemu. Po otrzymaniu tych informacji serwer przetwarza je i sprawdza czy dany użytkownik powinien uzyskać dostęp do żądanego zasobu.
Wykorzystanie tej metody uwierzytelniania też można włączyć w oknie dialogowym Metody uwierzytelnienia przedstawionym na rysunku 21.5. Trzeba jednak wiedzieć, iż ta metoda uwierzytelniania działa wyłącznie wtedy, gdy zarówno klient jak i serwer działają w systemie operacyjnym Windows. Warto także zauważy, iż jeśli zaznaczymy kilka metod uwierzytelniania, to ta najbardziej restrykcyjna będzie miała największy priorytet (na przykład, zintegrowane uwierzytelnianie systemu Windows zostanie wykorzystane zamiast dostępu anonimowego).
Zazwyczaj zintegrowane uwierzytelnianie sytemu Windows jest wykorzystywane w tych przypadkach gdy chcemy użyć prostej w implementacji metody uwierzytelniania, która wymaga jak najmniejszych modyfikacji w kodzie stron ASP.NET. W takim przypadku wystarczy bowiem wybrać odpowiednie ustawienia konfiguracyjne w serwerze IIS.
Zarówno uwierzytelnianie bazujące na skrótach jak i zintegrowane uwierzytelnianie systemu Windows wymagają, aby użytkownik korzystał z przeglądarki Microsoft Internet Explorer, co oznacza iż przed wykorzystaniem którejkolwiek z tych metod konieczne będzie skonsultowanie się z użytkownikami aplikacji. Co więcej, uwierzytelnianie bazujące na skrótach działa wyłącznie na niektórych typach serwerów; więcej informacji na ten temat można znaleźć w artykule:
http://support.microsoft.com/support/kb/articles/q222/0/28.asp
Uwierzytelnianie za pośrednictwem formularza
Technologia ASP.NET daje możliwość realizacji uwierzytelniania nie za pośrednictwem serwera IIS, lecz tworzonej aplikacji ASP.NET. Jest to możliwe dzięki wykorzystaniu mechanizmu określanego jako uwierzytelnianie za pośrednictwem formularzy. Mechanizm ten daje znacznie większą kontrolę nad używanym sposobem uwierzytelniania. Na przykład, dane uwierzytelniające użytkowników mogą być przechowywane w bazie danych lub w pliku XML; nie musi nimi wcale zarządzać bezpośrednio system operacyjny Windows.
Przy wykorzystaniu tej metody uwierzytelniania użytkownicy są kierowani do specjalnego formularza wchodzącego w skład aplikacji ASP.NET, który służy do podawania informacji uwierzytelniających. Następnie aplikacja przeprowadza uwierzytelnienie użytkownika przy użyciu algorytmu określonego przez jej twórcę. Jeśli dane zostaną zaakceptowane, to ASP.NET tworzy specjalne cookie autoryzacyjne, które jest następnie przesyłane i zapamiętywane na komputerze użytkownika (więcej informacji na temat cookies można znaleźć w rozdziale 4, pt.: „Stosowanie obiektów ASP.NET w językach C# i VB.NET”). Cookie to zawiera bądź to zapisane w dowolnej postaci informacje uwierzytelniające, bądź też łańcuch znaków, który umożliwi późniejsze pobranie danych uwierzytelniających. Informacje zapisane w tym cookie będą następnie używane do uwierzytelniania użytkownika w całej aplikacji. Poniżej opisany został przebieg całego procesu uwierzytelniania przy wykorzystaniu formularza:
Klient żąda dostępu do chronionej strony.
Jeśli wraz z żądaniem nie zostało przesłane ważne cookie uwierzytelniające, to serwer przekierowuje przeglądarkę pod adres URL określony w atrybucie loginURL dyrektywy Authentication zapisanej w pliku konfiguracyjnym web.config. Pod podanym adresem powinien znajdować się formularz służący do logowania użytkowników.
Użytkownik podaje dane uwierzytelniające w formularzu, a następnie wysyła go (dane są przesyłane na serwer metodą POST).
Jeśli dane uwierzytelniające podane przez użytkownika są poprawne (co można określić na kilka różnych sposobów, o których będzie mowa w dalszej części rozdziału), to ASP.NET tworzy cookie uwierzytelniające i przesyła je do klienta.
Teraz użytkownik może zostać przekierowany do strony, którą chciał wyświetlić.
Proces ten został zilustrowany na rysunku 21.8.
Rysunek 21.8. Sposób działania uwierzytelniania za pośrednictwem formularza
Opis rysunku
Client request — Użytkownik zgłasza żądanie
IIS — IIS
Allow through — Zezwala na przekazanie żądania
Allow access — Użytkownik uzyskuje prawo dostępu do zasobu
Yes — Tak
No — Nie
Is authorized… — Czy jest dostępne cookie autoryzacyjne?
Direct user … — Przekierowanie użytkownika do formularza logowania
User … — Pobranie danych uwierzytelniających
Authenticated? — Czy uwierzytelniony?
Deny … — Brak dostępu do zasobu
Set … — Stworzenie cookie uwierzytelniającego
Po utworzeniu cookie uwierzytelniającego wszystkie żądania przesyłane przez danego użytkownika będą automatycznie uwierzytelniane aż do momentu zamknięcia przeglądarki i zakończenia sesji. Po zakończeniu sesji, jeśli użytkownik ponownie spróbuje uzyskać dostęp do chronionych zasobów, będzie się musiał ponownie zalogować. Jak się wkrótce przekonamy, istnieje także możliwość by cookie uwierzytelniające nie było usuwane. Dzięki temu, jeśli użytkownik choć raz się zaloguje i zostanie poprawnie uwierzytelniony, już nigdy nie będzie musiał logować się ponownie.
Przyjrzymy się teraz ustawieniom jakie należy podać w pliku konfiguracyjnym web.config, aby wykorzystać autoryzację za pośrednictwem formularza.
<configuration>
<system.web>
<authentication mode="Forms">
<forms name="nazwa" loginUrl="adresFormularzaLogowania" />
</authentication>
</system.web>
</configuration>
Trzeci wiersz powyższego fragmentu kodu informuje, że wykorzystywana jest autoryzacja realizowana za pośrednictwem formularza. W kolejnym, czwartym wierszu określana jest nazwa cookie autoryzacyjnego oraz adres URL strony zawierającej formularz służący do logowania użytkowników.
Nadszedł czas, aby przedstawić odpowiedni przykład. Dla folderu /aspnetdlakazdego/rozdzial21 wyłącz wszystkie metody uwierzytelniania realizowanego przez IIS i zezwól na dostęp anonimowy (informacje na temat tego jak należy to zrobić, zostały podane we wcześniejszej części rozdziału, pt.: „Uwierzytelnianie systemu Windows”). Następnie, w głównym folderze aplikacji (w naszym przypadku jest to /aspnetdlakazdego) umieść plik konfiguracyjny web.config i dopisując do niego poniższy fragment kodu (pamiętaj aby umieścić go w odpowiedniej sekcji konfiguracyjnej — patrz poprzedni przykład).
<authenticate mode="Forms">
<forms name="AuthCookie" loginUrl="rozdzial21/login.aspx" />
</authenticate>
W przypadku poprawnego uwierzytelnienia użytkownika, zostanie utworzone cookie o nazwie AuthCookie. Jeśli wraz z żądaniem nie zostanie przesłane cookie o tej nazwie, to użytkownik zostanie przekierowany na stronę rozdzial21/login.aspx, która powinna zawierać formularz służący do logowania. Kolejnym krokiem będzie utworzenie strony login.aspx. Jej kod został przedstawiony na listingu 21.1.
Listing 21.1. Prosty formularza do logowania.
<%@ Page Language="VB" %>
<script runat="server">
sub Login(obj as object, e as eventargs)
if tbUserName.Text = "clpayne" and _
tbPassword.Text = "hello" then
FormsAuthentication.SetAuthCookie("clpayne", false)
Response.redirect("account.aspx")
else
lblMessage.Text = "<font color=red>Przykro mi, " & _
"nieprawidłowa nazwa użytkownika lub hasło!</font><p>"
end if
end sub
</script>
<html><body>
Proszą podać nazwę użytkownika i hasło.<p>
<form runat="server">
<asp:Label id="lblMessage" runat="server" />
Nazwa użytkownika:
<asp:Textbox id="tbUserName" runat="server" /><br>
Hasło:
<asp:Textbox id="tbPassword" TextMode="password"
runat="server" /><p>
<asp:Button id="Submit" runat="server"
OnClick="Zaloguj"
Text="Submit" />
</form>
</body></html>
Analiza
Formularz przedstawiony na powyższym listingu umożliwia użytkownikom podawanie swojej nazwy oraz hasła. Informacje te wpisywane są w polach tekstowych definiowanych w wierszach od 24. do 27. Po przesłaniu formularza wykonywana jest procedura Login, która sprawdza podane informacje i określa czy są one poprawne. Nasza strona jest jedynie bardzo prostym przykładem uwierzytelniania, a zatem, w 5. wierszu porównujemy podaną nazwę i hasło z zakodowanymi wartościami. Jeśli wartości będą sobie odpowiadać, to użytkownik zostanie uwierzytelniony. W wierszu 7. wywoływana jest metoda SetAuthCookie obiektu FormsAuthentication. Tworzy ona cookie uwierzytelniające zawierające podaną nazwę użytkownika, przekazaną jako pierwszy argument wywołania metody. Drugi argument wywołania tej metody określa czy cookie autoryzacyjne powinno zostać usunięte po zamknięciu przeglądarki czy też nie. Podanie wartości true spowoduje że cookie nie będzie usuwane, a użytkownik nie będzie musiał logować się nawet po ponownym uruchomieniu przeglądarki. W końcu, w wierszu 9. przeglądarka użytkownika zostaje przekierowana pod właściwy adres.
Jeśli dane uwierzytelniające podane w formularzu nie są poprawne, to instrukcja else zapisana w wierszu 10. wyświetli stosowny komunikat o błędzie. Na rysunku 21.9 zostały przedstawione wyniki wykonania tej strony w przypadku podania nieprawidłowych danych uwierzytelniających.
Rysunek 21.9. Wyniki działania formularza uwierzytelniającego po podaniu nieprawidłowych informacji.
Notatka
Podczas uwierzytelniania informacje wpisane przez użytkownika nie muszą być porównywane z danymi podanymi na stałe (tak jak w ostatnim przykładzie). W metodzie Login można zaimplementować dowolny sposób weryfikacji poprawności danych — w tym także wykorzystujący informacje przechowywane w bazie danych.
Oprócz elementu forms w pliku konfiguracyjnym można także umieszczać element credentials. Zawierają one nazwy użytkowników oraz odpowiadające im hasła, które należy wykorzystać przy uwierzytelnianiu użytkowników. Dzięki temu można porównywać informacje uwierzytelniające podane przez użytkownika z danymi przechowywanymi w pliku konfiguracyjnym web.config. Cały proces wygląda bardzo podobnie do tego z listingu 21.1, lecz jest wykonywany automatycznie.
Zmodyfikujmy plik web.config w poniższy sposób:
<configuration>
<system.web>
<authentication mode="Forms">
<forms name="AuthCookie" loginUrl="rozdzial21/login.aspx">
<credentials passwordFormat="Clear">
<user name="clpayne" password="helloworld" />
</credentials>
</forms>
</authentication>
</system.web>
</configuration>
Sekcja credentials zawiera poprawne informacje o użytkownikach, które powinne zostać wykorzystane przy uwierzytelnianiu żądań. Atrybut passwordFormat określa sposób szyfrowania danych uwierzytelniających, jaki powinien zostać wykorzystany przy ich przesyłaniu na serwer. Atrybut ten może przyjmować następujące wartości: Clear (dane nie są szyfrowane), MD5 lub SHA1 (obie te wartości określają doskonale znane algorytmy szyfrujące). Jeśli użytkownik korzysta z nowoczesnej wersji przeglądarki, to przy przesyłaniu danych uwierzytelniających będzie można wykorzystać każdą z metod szyfrowania.
Wewnątrz sekcji credentials umieszczane są elementy user. Każdy z nich zawiera dwa atrybuty — name oraz password (określają one odpowiednio nazwę użytkownika oraz hasło, które należy użyć w procesie uwierzytelniania). Należy zwrócić uwagę, iż nie ma żadnych ograniczeń co do ilości użytych elementów user. Na listingu 21.2 została przedstawiona strona ASP.NET uwierzytelniająca żądania na podstawie danych zapisanych w sekcji credentials pliku konfiguracyjnego web.config.
Listing 21.2. Uwierzytelnianie przy wykorzystaniu informacji zapisanych w sekcji credentials w pliku web.config (login2.aspx)
<%@ Page Language="VB" %>
<script runat="server">
sub Login(obj as object, e as eventargs)
if FormsAuthentication.Authenticate(tbUserName.Text, _
tbPassword.Text) then
FormsAuthentication.SetAuthCookie(tbUsername.Text, false)
lblMessage.Text = "<font color=red>Udało się!</font><p>"
else
lblMessage.Text = "<font color=red>Przykro mi, " & _
"nieprawidłowa nazwa użytkownik lub hasło!</font><p>"
end if
end sub
</script>
<html><body>
Proszą podać nazwę użytkownika i hasło.<p>
<form runat="server">
<asp:Label id="lblMessage" runat="server" />
Nazwa użytkownika:
<asp:Textbox id="tbUserName" runat="server" /><br>
Hasło:
<asp:Textbox id="tbPassword" TextMode="password"
runat="server" /><p>
<asp:Button id="btSubmit" runat="server"
OnClick="Login"
Text="Zaloguj" />
</form>
</body></html>
Analiza
Powyższy formularz jest bardzo podobny do formularza z poprzedniego listingu, zawiera dokładnie te same elementy sterujące oraz procedurę obsługi zdarzenia. Oba przykłady różnią się w zasadzie wyłącznie kodem umieszczonym w wierszu 5. W tym przypadku, dane uwierzytelniające są porównywane nie z informacjami podanymi na stałe (jak było w poprzednim przypadku) lecz zostają one przekazane do metody Authenticate obiektu FormsAuthentication. Metoda ta wymaga podania dwóch argumentów — nazwy użytkownika oraz hasła — które następnie porównuje z informacjami zapisanymi w sekcji credentials pliku konfiguracyjnego web.config. Jeśli dane uwierzytelniające przesłane z formularza odpowiadają informacjom podanym w którymkolwiek z elementów user, to metoda Authenticate zwróci wartość true; w takim przypadku można stworzyć cookie uwierzytelniające (patrz wiersz 7.). Jak zatem widać, plik konfiguracyjny web.config udostępnia bardzo łatwy sposób definiowania użytkowników.
Klasa FormsAuthentication, z której korzystaliśmy w dwóch ostatnich przykładach udostępnia wiele dodatkowych metod których można użyć przy uwierzytelnianiu użytkowników oraz kontroli żetonów uwierzytelniających. Poznaliśmy już dwie metody tej klasy — Authenticate oraz SetAuthCookie, którymi posługiwaliśmy się w poprzednich przykładach.
Gdy użytkownik żąda dostępu do chronionej strony, mechanizmy ASP.NET automatycznie przekierują jego przeglądarkę pod adres URL podany w atrybucie loginUrl elementu konfiguracyjnego forms. W przypadku przekierowania adres URL strony której początkowo dotyczyło żądanie zostaje zapisany w łańcuchu zapytania, dzięki czemu będzie go można później użyć. Jak na razie wartość ta była przez nas całkowicie ignorowana, jednak po poprawnym uwierzytelnieniu użytkownika można jej użyć do przekierowania jego przeglądarki pod właściwy adres.
Metoda RedirectFromLoginPage klasy FormsAuthentication przypomina metodę SetAuthCookie — także tworzy cookie uwierzytelniające, lecz dodatkowo powoduje także przekierowanie przeglądarki użytkownika pod adres URL, którego początkowo dotyczyło żądanie. Jeśli w łańcuchu zapytania nie zostały zapisane informacje o żądanej stronie, to metoda ta przekieruje przeglądarkę użytkownika na stronę default.aspx znajdującą się w głównym folderze aplikacji. Na przykład, procedurę Login z listingu 21.2 można by zmienić w następujący sposób:
sub Login(obj as object, e as eventargs)
if FormsAuthentication.Authenticate(tbUserName.Text, _
tbPassword.Text) then
FormsAuthentication.RedirectFromLoginPage _
(tbUsername.Text, false)
lblMessage.Text = "<font color=red>Udało się!</font><p>"
else
lblMessage.Text = "<font color=red>Przykro mi, " & _
"nieprawidłowa nazwa użytkownik lub hasło!</font><p>"
end if
end sub
Jeśli zażądamy tej strony bezpośrednio, to po pomyślnym uwierzytelnieniu użytkownika zostanie wyświetlona strona default.aspx. Nie można zatem o niej zapomnieć! Metoda RedirectFromLoginPage jest przydatna do przesyłania użytkowników na stronę którą chcieli oglądnąć jednak brakuje jej możliwości wykonania jakichkolwiek czynności po stworzeniu cookie uwierzytelniającego. Aby wygenerować cookie uwierzytelniające i pobrać adres strony której początkowo dotyczyło żądanie bez przechodzenia do niej, można użyć metody GetRedirectURL:
dim strURL = FormsAuthentication.GetRedirectURL("uzytkownik", false)
Klasa FormsAuthentication udostępnia także inną przydatną metodę — GetAuthCookie. Tworzy ona obiekt klasy HttpCookie zawierający informacje uwierzytelniające (więcej informacji na temat klasy HttpCookie można znaleźć w rozdziale 4.). Metoda ta nie powoduje jednak wygenerowania tego cookie i zapamiętania go na komputerze użytkownika. Ma ona jednak tą zaletę, iż pozwala na wykonanie jakichś czynności po utworzeniu cookie autoryzacyjnego i przed jego przekazaniem do przeglądarki użytkownika. Na przykład, wykorzystując ją można dodać do cookie uwierzytelniającego jakieś dowolne, dodatkowe informacje. Nie można jednak zapominać o wygenerowaniu cookie po zakończeniu wykonywania dodatkowych czynności. Jeśli tego nie zrobimy, to użytkownik nie zostanie uwierzytelniony. Stosowny przykład przedstawiony został na listingu 21.3.
Listing 21.3. Wykorzystanie metody GetAuthCookie do wzbogacenia informacji przechowywanych w cookie uwierzytelniającym.
<%@ Page Language="VB" %>
<script runat="server">
sub Login(obj as object, e as eventargs)
if FormsAuthentication.Authenticate(tbUserName.Text, _
tbPassword.Text) then
dim cookie as HttpCookie
cookie = FormsAuthentication.GetAuthCookie("clpayne", false)
cookie.Expires = DateTime.Now.AddMinutes(2)
Response.Cookies.Add(cookie)
lblMessage.Text = "<font color=red>Udało się!</font><p>"
else
lblMessage.Text = "<font color=red>Przykro mi, " & _
"nieprawidłowa nazwa użytkownik lub hasło!</font><p>"
end if
end sub
</script>
Analiza
Powyższy przykład niewiele różnic się od przykładów z listingów 21.1 oraz 21.2; dlatego też w powyższym listingu został pominięty kod HTML definiujący interfejs użytkownika tej strony. W wierszu 8. powyższego przykładu tworzona jest zmienna klasy HttpCookie, w której zostanie zapisane cookie uwierzytelniające. Wywołanie metody GetAuthCookie zapisane w wierszu 10. tworzy nowe cookie i zapisuje go w zmiennej cookie. Warto zwrócić uwagę, iż w wywołaniu metody używane są takie same argumenty co w wywołaniu metody SetAuthCookie. Teraz, przed zakończeniem uwierzytelniania użytkownika będziemy mogli w dowolny sposób zmodyfikować uzyskane cookie. Na przykład, w wierszu 11. zmieniamy datę wygaśnięcia ważności cookie i ustawiamy ją na dwie minuty od chwili obecnej. Po wprowadzaniu wszystkich niezbędnych modyfikacji należy wygenerować cookie dodając je do kolekcji Response.Cookies (patrz wiersz 13.).
Klasa FormsAuthentication udostępnia także metodę SignOut, która pozwala na wylogowanie danego użytkownika. Metoda ta usuwa cookie autoryzacyjne co sprawia, że przy ponownej próbie dostępu do chronionych zasobów użytkownik będzie się musiał ponownie zalogować. Wiele witryn które wymuszają na użytkownikach konieczność logowania, udostępniają także możliwość wylogowania, która jest dodatkowych mechanizmem zabezpieczającym. Dzięki niej, użytkownicy korzystający z tego samego komputera nie muszą używać tego samego konta na witrynie. Aby wylogować użytkownika wystarczy skierować go na stronę, która wykona metodę SignOut:
FormsAuthentication.SignOut
Uwierzytelnianie za pośrednictwem formularzy ma ogromne możliwości i daje programistom dużą elastyczność co do sposobu implementacji uwierzytelniania. Co więcej jest to metoda łatwa do wykorzystania, gdyż stosowane przez nią ustawienia są podawane w pliku konfiguracyjnym web.config. Na przykład, można zapisać informacje o użytkownikach w bazie danych i stworzyć własne metody uwierzytelniania, choć z drugiej strony rozwiązanie takie uniemożliwi autoryzowanie użytkowników przy użyciu metody Authenticate.
Uwierzytelnianie przy użyciu usługi Passport
Passport to scentralizowana usługa uwierzytelniania (nie ma ona nic wspólnego z serwisami sieci WWW) prowadzona przez firmę Microsoft. Działa ona bardzo podobnie do uwierzytelniania za pośrednictwem formularzy, z tą drobną różnicą iż żadnych możliwości funkcjonalnych nie trzeba implementować samodzielnie. Podstawą działania obu tych metod są cookies przechowywane na komputerach użytkowników i wykorzystywane przy uwierzytelnianiu. W razie wykorzystania uwierzytelniania przy użyciu usługi Passport użytkownicy wchodzący na chronioną stronę są kierowani na specjalną stronę logowania zawierającą bardzo prosty formularz, który należy wypełnić i przesłać (więcej informacji na ten temat można znaleźć na witrynie http://www.passport.com). Formularz ten sprawdza dane uwierzytelniające użytkownika porównując je z danymi zgromadzonymi przez usługę Passport i określa czy są one poprawne czy nie. Jeśli użytkownik zostanie poprawnie uwierzytelniony, to podobnie jak w poprzedniej metodzie, generowane jest cookie uwierzytelniające. Poniżej opisane zostały poszczególne czynności wykonywane podczas uwierzytelniania tą metodą:
Klient żąda chronionej strony z naszej witryny.
Jeśli żądanie nie zawiera ważnego cookie uwierzytelniającego stosowanego przez usługę Passport, to serwer przekazuje żądanie do mechanizmu logowania usługi Passport. Jednocześnie przekazywane są także dodatkowe, zaszyfrowane informacje dotyczące żądania.
W przeglądarce użytkownika wyświetlany jest formularz logowania usługi Passport. Informacje uwierzytelniające są podawane w tym formularzu, a następnie zostają przesłane do usługi Passport przy użyciu bezpiecznego protokołu SSL.
Jeśli informacje są poprawne, usługa Passport tworzy żeton uwierzytelniający i umieszcza go w łańcuchu zapytania, po czym kieruje użytkownika na witrynę którą chciał odwiedzić.
Gdy serwer odnajdzie żeton uwierzytelniający w łańcuchu zapytania, tworzy dla danego użytkownika cookie uwierzytelniające.
Jak zatem widać, usługa Passport w zasadzie nie tworzy cookie uwierzytelniającego — za realizację tego zadania jest odpowiedzialny serwer WWW do którego zostało skierowane żądanie.
Prawdopodobnie nie będziesz zajmować się bardziej szczegółowo tą usługa, gdyż w tym celu Twoja witryna musiałby by być zarejestrowanym członkiem usługi Microsoft Passport. Co więcej, aby zostać członkiem tej usługi konieczne jest wniesienie stosownych opłat. Jeśli chcesz zdobyć więcej informacji na temat usługi Microsoft Passport możesz skorzystać z jej dokumentacji, znajdującej się pod adresem http://www.passport.com/business. Kiedy już zarejestrujesz się jako członek usługi Microsoft Passport, będziesz musiał Passport SDK i odpowiednie skonfigurować swoją aplikację.
Ostatnim etapem przygotowywania aplikacji do wykorzystania uwierzytelniania przy wykorzystaniu usługi Passport, jest odpowiednie zmodyfikowanie pliku konfiguracyjnego web.config. Oto przykładowa postać takiego pliku, jak widać jest ona całkiem prosta:
<configuration>
<system.web>
<authentication mode="Passport">
</authentication>
</system.web>
<configuration>
Wykorzystanie usługi Microsoft Passport jest bardzo przydatnym i prostym sposobem implementacji na własnej witrynie mechanizmów uwierzytelniających, którym można w pełni zaufać. Z usługi tej korzysta już bardzo wiele witryn, w tym także (co nie jest żadnym zaskoczeniem) wszystkie witryny firmy Microsoft. Kiedy ktoś zarejestruje się już w usłudze Microsoft Passport i otrzyma swoją własną „tożsamość”, to posługując się tą samą nazwą użytkownika i hasłem będzie w stanie uzyskać dostęp do wszystkich witryn korzystających z tego sposobu uwierzytelniania. Z tego względu, jeśli myślisz w ogóle o nawiązaniu współpracy z inną witryną lub stworzenia grupy witryn, to usługa Microsoft Passport może być doskonałym mechanizmem zabezpieczającym.
Autoryzacja
Nowe wyrażenie
Przypominasz sobie zapewne, że każdy system zabezpieczający spełnia dwie funkcje — uwierzytelnia użytkowników oraz ich autoryzuje. Jak się przekonaliśmy, autoryzacja jest procesem polegającym na określeniu tożsamości użytkownika na podstawie pewnych informacji. Z kolei autoryzacja polega na określeniu zasobów, z jakich ten użytkownik może korzystać. W technologii ASP.NET proces autoryzacji można wykonać na dwa sposoby. Po pierwsze może on bazować na systemie operacyjnym Windows, który zwraca informacje o tym, do jakich zasobów ma dostęp konkretny, uwierzytelniony użytkownik. Metoda ta nazywana jest autoryzacją dostępu do plików. Alternatywnym rozwiązaniem jest autoryzacja bazująca na adresie URL żądanego zasobu; w tym przypadku proces ten nosi nazwę autoryzacji dostępu do adresów URL. Konfiguracja i wykorzystanie obu tych metod nie przysparza najmniejszych problemów.
Zanim przedstawię sposób działania autoryzacji dostępu do plików przyjrzyjmy się, w jaki sposób system operacyjny obsługuje mechanizmy zabezpieczeń. Uruchom Eksploratora Windows, kliknij prawym przyciskiem myszy na dowolnym folderze (na przykład c:\winnt) i z menu podręcznego wybierz opcję Właściwości, a następnie przejdź na zakładkę Zabezpieczenia; powinna ona przypominać tę z rysunku 21.10.
Rysunek 21.10. Opcje zabezpieczeń systemu operacyjnego
Jeśli używasz systemu operacyjnego Windows NT lub Windows 2000 i Twój dysk twardy został sformatowany w systemie NTFS (więcej informacji na ten temat można znaleźć w dokumentacji systemu operacyjnego), to będzie można określać opcje zabezpieczeń niezależnie dla każdego folderu i pliku zapisanego na dysku.
Opcje te uprawniają użytkowników do odczytywania zawartości pliku, zapisywania w nim danych, wykonywania aplikacji czy też przeglądania zawartości folderów (patrz lista Uprawnienia widoczna u dołu rysunku 21.10). Wszystkie te informacje o prawach dostępu do plików i folderów, są przechowywane w listach kontroli dostępu (ang.: Access Control Lists, w skrócie ACL) obsługiwanych przez system operacyjny Windows. Modyfikacja poszczególnych praw dostępu do wybranych elementów systemu plików jest bardzo łatwa, gdyż sprowadza się do zaznaczania lub usuwania znacznika z odpowiednich pól wyboru na zakładce Zabezpieczenia.
W przypadku wykorzystania autoryzacji dostępu do plików, ASP.NET prowadzi interakcję z systemem operacyjnym w celu powiązania tożsamości użytkownika z informacjami zapisanymi na listach kontroli dostępu. Gdy uwierzytelniony użytkownik spróbuje uzyskać dostęp do jakiegoś pliku na serwerze WWW, system operacyjny sprawdzi odpowiednie listy kontroli dostępu, aby określić czy dany użytkownik lub dana rola ma prawa konieczne do wyświetlenia zawartości tego pliku. Wszystkie te czynności są wykonywane w sposób automatyczny i niezauważalny. Dzięki temu ten sposób autoryzacji jest bardzo prosty do wykorzystania. Przy określaniu uprawnień na podstawie list kontroli dostępu, autoryzacja dostępu do plików współdziała z procesem personifikacji. (Więcej informacji na temat tego procesu znajdziesz w dalszej części niniejszego rozdziału, pt.: „Personifikacja”.)
Niemniej jednak zarządzanie listami kontroli dostępu może być prawdziwym utrapieniem. Wyobraźmy sobie, że nasza witryna składa się z 50 folderów, a w każdym z nich jest przechowywanych kilka plików. W takim przypadku zarządzanie listami kontroli dostępu może być niezwykle uciążliwe. Właśnie z tego powodu ASP.NET udostępnia także możliwość autoryzacji w oparciu o adresy URL. Metoda ta polega na odwzorowaniu tożsamości użytkownika na foldery znajdujące się w żądanych --> adresach URL[Author:p8R] .
Aby umożliwić wykorzystanie tego sposobu autoryzacji, należy wprowadzić kilka zmian w pliku konfiguracyjnym web.config. Poniżej przedstawiona została składnia znacznika authorization:
<authorization>
<allow users="listaUżytkownikówOddzialonychPrzecinkami"
roles="listaRólOddzielonychPrzecinkami" />
<deny users="listaUżytkownikówOddzialonychPrzecinkami"
roles="listaRólOddzielonychPrzecinkami" />
<authorization>
Znaczniki allow oraz deny określają tożsamości jakim należy udzielić bądź odmówić dostępu do zasobów. Gdybyśmy umieścili plik web.config przedstawiony na kolejnym przykładzie w głównym folderze witryny, u użytkownik clpayne dysponował by dostępem do wszystkich zasobów, natomiast użytkownik janek nie mógłby skorzystać z żadnego z nich (oczywiście zakładając, że w aplikacji nie jest wykorzystywany żaden inny plik konfiguracyjny, który mógłby przesłonić ustawienia naszego przykładowego pliku web.config).
<authorization>
<allow users="clpayne" />
<deny users="janek" />
</authorization>
Przy użyciu znaczników allow oraz deny można określać informacje autoryzacyjne zarówno dla tożsamości użytkowników jak i dla ról. Oznacza to, że w bardzo prosty sposób można zabronić dostępu do pewnego zasobu całej grupie użytkowników — wystarczy podać w znaczniku deny nazwę roli do której wszyscy Ci użytkownicy należą.
Notatka
Należy zauważyć, iż uprawnienia podawane w znacznikach allow oraz deny obowiązują wyłącznie w folderze w którym znajduje się odpowiedni plik konfiguracyjny web.config oraz we wszystkich folderach podrzędnych. Innymi słowy uprawnienia te są stosowane podobnie jak wszystkie inne ustawienia konfiguracyjne podawane w plikach web.config — zgodnie z hierarchiczną strukturą systemu konfiguracyjnego.
ASP.NET udostępnia dwie specjalne tożsamości, umożliwiające dalsze grupowanie użytkowników. Znak zapytania ("?") umieszczony w atrybucie users oznacza użytkowników anonimowych — czyli tych, którzy nie zostali w żaden sposób uwierzytelnieni. Natomiast gwiazdka ("*") oznacza wszystkich użytkowników niezależnie od tego czy zostali oni uwierzytelnieni czy nie. Przedstawiony poniżej przykład pokazuje w jaki sposób można udzielić dostępu do pewnego zasobu wyłącznie uwierzytelnionym użytkownikom:
<authorization>
<deny users="?" />
</authorization>
Z drugiej strony, kolejny przykład pokazuje jak udzielić dostępu do pewnego folderu wszystkich możliwym użytkownikom:
<authorization>
<allow users="*" />
</authorization>
Powyższy przykład demonstruje domyślne ustawienia wykorzystywane przez ASP.NET w przypadku, gdy nie zostały wybrane żadne inne metody uwierzytelniania i autoryzacji.
Oprócz możliwości określania użytkowników oraz ról, technologia ASP.NET pozwala także na autoryzację dostępu do zasobów na podstawie sposobu w jaki użytkownicy się do nich odwołują. Atrybut verb określa metodę protokołu HTTP przy użyciu której można uzyskać dostęp do danego zasobu. Metodami tymi są — GET oraz POST. Przykładowo, poniższy fragment pliku konfiguracyjnego pozwala by wszyscy użytkownicy pobierali zasoby przy użyciu metody GET, jednak tylko użytkownikowi piotr danej możliwość pobierania ich przy użyciu metody POST:
<authorization>
<allow verb="GET" users="*" />
<allow verb="POST" users="piotr" />
<deny verb="POST" users="?" />
</authorization>
Ale czy kiedykolwiek będziemy chcieli wykorzystać taki schemat udzielania praw dostępu do zasobów? Wyobraźmy sobie, że zaimplementowaliśmy na stronach ASP.NET niezwykle przydatne możliwości funkcjonalne — na przykład kalkulator obliczający raty kredytów. Chcemy, aby każdy mógł oglądnąć ten kalkulator i wypróbować jego podstawowe możliwości. Jednak jednocześnie chcemy, aby tylko zarejestrowani użytkownicy mogli korzystać z pełnych możliwości kalkulatora, gdyż wymaga to przesyłania danych na serwer. Czyli wszyscy mogą pobieżnie zapoznać się z możliwościami kalkulatora, co powinno zachęcić użytkowników do zarejestrowania się i uzyskania pełnego dostępu do jego możliwości.
Choć taki hierarchiczny system konfiguracyjny jest bardzo wygodny, to jednak nie daje dużych możliwości wybiórczej kontroli. Na przykład, ustawienia podane w pliku web.config dotyczą plików znajdujących się w tym samym folderze oraz we wszystkich folderach podrzędnych. Aby zmienić ustawienia konfiguracyjne w folderach podrzędnych, trzeba będzie stworzyć odpowiedni plik konfiguracyjny web.config w każdym z nich. Szczerze mówiąc, bardzo nieznacznie różni się to od problemów występujących przy zarządzaniu listami praw dostępu.
Jednak pliki konfiguracyjne web.config pozwalają na znacznie bardziej szczegółowe określanie jakich zasobów dotyczą definiowane w nich ustawienia. Możliwości te zapewniają znaczniki location, które można umieszczać we wszystkich plikach web.config. Znaczniki te określają zasoby jakich dotyczą definiowane ustawienia konfiguracyjne, zgodnie ze strukturą folderów witryny. Na przykład, umieszczając plik konfiguracyjny --> z listingu 21.4[Author:p8R] w głównym folderze witryny można kontrolować autoryzację w kilku folderach podrzędnych. Zresztą zobacz sam.
Listing 21.4. Plik web.config umożliwiający kontrolę dostępu do kilku folderów.
<configuration>
<location path="rozdzial21/account.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
<location path="rozdzial21/folder2">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
</configuration>
Analiza
W wierszu 2. określamy, że podawane informacje konfiguracyjne będą dotyczyć pliku rozdzial21/accounts.aspx. W wierszu 4., przy użyciu znacznika authorization uniemożliwiamy dostęp do tego pliku wszystkim użytkownikom anonimowym. W wierszu 11. informujemy, że kolejne ustawienia będą dotyczyć folderu rozdzial21/folder2/. Ustawienia ta uniemożliwiają dostęp do zawartości tego folderu użytkownikom anonimowym. W ten sposób, w pliku web.config można zdefiniować ustawienia konfiguracyjne dla dowolnej ilości plików i folderów niezależnie od ich położenia w strukturze folderów witryny.
Należy zwrócić uwagę, iż znaczniki location są umieszczone na zewnątrz znaczników authorization. Często spotykanym błędem popełnianym przez początkujących programistów, jest zapisywanie tych dwóch znaczników w odwrotnej kolejności — czyli znaczników location wewnątrz znaczników authorization. Warto także wiedzieć, że informacje autoryzacyjne dotyczące każdego folderu trzeba podawać w odrębnej sekcji location.
Personifikacja
Personifikacja pozwala technologii ASP.NET na wykonywanie strony przy wykorzystaniu tożsamości klienta którego żądanie jest obsługiwane. Innymi słowy, jeśli użytkownik został uwierzytelniony jako clpayne, to ASP.NET zabroni lub udzieli mu dostępu do zasobów na podstawie praw dostępu określonych dla tego użytkownika.
Ale chwileczkę! Czy przez przypadek nie jest to standardowy sposób działania? Przeanalizujmy schemat przedstawiony na rysunku 21.11, aby wszystko lepiej zrozumieć.
Rysunek 21.11. Przebieg procesu wykonywania stron ASP.NET w przypadku wykorzystania personifikacji
Opis rysunku
User makes request — Użytkownik przesyła żądanie
IIS — IIS
User authenticated — Czy użytkownik został uwierzytelniony?
Yes — Tak
No — Nie
Deny access — Brak dostępu do zasobu
ASP.NET — ASP.NET
Impersonalization … — Personifikacja włączona?
ASP.NET assumes … — ASP.NET przyjmuje tożsamość użytkownika
Application … — Aplikacja zostanie uruchomiona przy wykorzystaniu tożsamości IIS
ACLs allow… — Czy listy kontroli dostępu zezwalają na dostęp?
Access granted — Udzielony dostęp do zasobu
Domyślnie mechanizm personifikacji jest wyłączony. W tym przypadku, gdy zakończy się etap uwierzytelniania użytkownika przez IIS i obsługa żądania zostanie przekazana do aplikacji ASP.NET, to mechanizmy ASP.NET będą wykonywane przy użyciu tożsamości nadanej serwerowi IIS (zazwyczaj jest to „Lokalny komputer”). Zazwyczaj tożsamość ta dysponuje prawami dostępu do wszystkich plików i folderów. Do obsługi dostępu należy wykorzystać inne mechanizmy zabezpieczeń, takie jak autoryzacja dostępu do adresów URL.
Jeśli jednak personifikacja zostanie włączona, to ASP.NET przyjmuje tożsamość przekazaną przez IIS. Jeśli użytkownik nie został uwierzytelniony, to ASP.NET przyjmie tożsamość użytkownika anonimowego. W przeciwnym przypadku, jeśli użytkownik został uwierzytelniony to ASP.NET wykorzysta jego tożsamość. Dzięki temu, że teraz ASP.NET działa jako inny użytkownik, system operacyjny Windows może ograniczyć dostęp do aplikacji, na podstawie informacji zapisanych w listach praw dostępu.
Aplikacje ASP.NET są użytkownikami zasobów systemowych. Korzystają one z plików, folderów, pamięci, itp. Domyślnie proces aplikacji ASP.NET ma duże uprawnienia i ogólnie rzecz biorąc może uzyskać dostęp do wszystkich zasobów dostępnych w systemie operacyjnym. To konieczne, gdyż ASP.NET potrzebuje tych zasobów do poprawnego funkcjonowania. Niemniej jednak w niektórych sytuacjach będziemy chcieli ograniczać dostęp do określonych zasobów, w zależności od użytkownika który korzysta z aplikacji ASP.NET. Na przykład, użytkownik anonimowy nie powinien mieć możliwości skorzystania z tego, iż aplikacja dysponuje prawami dostępu do wszystkich zasobów systemowych. Właśnie do tego służy mechanizm personifikacji, który pozwala ASP.NET przyjąć tożsamość użytkownika i na tej podstawie określić prawa dostępu jakimi dysponuje.
Gdy ASP.NET przyjmuje tożsamość użytkownika, to pod każdym względem działa tak jak on. W rzeczywistości, system operacyjny będzie sądził, że to właśnie dany użytkownik korzysta z zasobów systemowych. W tej sytuacji można wykorzystać listy kontroli dostępu i na ich podstawie ograniczać dostęp do zasobów zarówno ASP.NET jak i użytkownikowi.
Wyobraźmy sobie typowy schemat działania w przypadku włączonej personifikacji. Otóż naszą witrynę odwiedza zarejestrowany użytkownik JanNowak, który nie dysponuje żadnymi uprawnieniami administracyjnymi. Gdy tylko użytkownik zostanie uwierzytelniony, ASP.NET przyjmuje jego tożsamość i cały kod jest wykonywany w taki sposób, jak gdyby realizował go użytkownik JanNowak zalogowany na lokalnym serwerze a nie ASP.NET.
Jedna ze stron na naszej witrynie, na przykład files.aspx, wyświetla listę wszystkich plików dostępnych na serwerze i umożliwia zarządzanie nimi. Oczywiście dostęp do tej strony powinni mieć wyłącznie administratorzy. Jeśli użytkownik JanNowak spróbuje uzyskać dostęp do tej strony, to ASP.NET (które aktualnie działa jako użytkownik JanNowak) nie będzie w stanie wykonać tego kodu, gdyż użytkownik JanNowak nie ma uprawnień do odczytu wszystkich plików na serwerze. Jak zatem widać, personifikacja uniemożliwia użytkownikom korzystanie z plików, do których nie mają dostępu. Jednak, czy ASP.NET nie powinno domyślnie stosować takich mechanizmów zabezpieczających? Otóż nie. Domyślnie ASP.NET przyjmuje że są wykorzystywane inne mechanizmy uwierzytelniania i autoryzacji, a zatem personifikacja nie jest konieczna. Na przykład, przy wykorzystaniu uwierzytelniania systemu Windows, można uniemożliwić użytkownikowi dostęp do zasobów, zanim w ogóle będzie w stanie wykorzystać jakąś stronę ASP.NET. W tym przypadku personifikacja nie jest konieczna, gdyż użytkownik nigdy nie będzie w stanie wykonać programu. Niemniej jednak, jeśli użytkownik może uzyskać dostęp do plików, z których nie powinien korzystać, to w takich sytuacjach personifikacja jest bardzo przydatna.
Notatka
Nawet w przypadku wykorzystania personifikacji ASP.NET będzie korzystać z własnej tożsamości, aby pobierać informacje z plików konfiguracyjnych. Gdyby było inaczej, aplikacje nie mogłyby działać poprawnie. Na przykład, większość użytkowników nie ma dostępu do plików systemowych, takich jak machine.config, w który są przechowywane informacje o sposobie konfiguracji wszystkich aplikacji ASP.NET.
A zatem dlaczego mielibyśmy rezygnować z wykorzystania personifikacji, jeśli udostępnia ona tak wygodne mechanizmy kontroli dostępu? Przypomnij sobie, że zarządzanie uprawnieniami użytkowników przy użyciu list kontroli dostępu jest dosyć kłopotliwe. Bardzo często lepszym rozwiązaniem jest zastosowanie innych metod autoryzacji, na przykład, autoryzacji dostępu do adresów URL. Co więcej, aby skorzystać z personifikacji konieczne jest uwierzytelnianie użytkowników przez serwer IIS, a takiego rozwiązania niektórzy twórcy aplikacji wolą unikać.
Tak |
Nie |
Personifikacji warto używać jeśli chcemy skrócić czas konieczny do stworzenia kodu ASP.NET. W przypadku wykorzystania personifikacji, pozostaje tylko zastosować mechanizmy uwierzytelniania serwera IIS i zarządzać listami kontroli dostępu. |
Nie warto korzystać z personifikacji jeśli planujemy stworzenie własnych mechanizmów uwierzytelniania. |
Włączanie personifikacji jest bardzo proste — wystarczy dodać jeden wiersz kodu do pliku web.config:
<configuration>
<system.web>
<identity impersonate="true" username="użytkownik"
password="hasło" />
</system.web>
</configuration>
Jedynym wymaganym atrybutem znacznika identity jest impersonate. Jeśli atrybut ten będzie miał wartość true, to personifikacja zostanie włączona. Jeśli w znaczniku identity zostaną podane dwa opcjonalne atrybuty username oraz password, będzie to oznaczało, iż ASP.NET zawsze ma używać tożsamości podanego użytkownika; w tym przypadku informacje o użytkownikach uwierzytelnionych przez IIS są ignorowane. Możliwość ta jest bardzo przydatna w sytuacjach, gdy wszyscy użytkownicy mają mieć dokładnie te same uprawnienia.
Przykładowo załóżmy, że dysponujemy wieloma użytkownikami systemu Windows, którzy powinni posiadać dokładnie te same uprawnienia. Ze względu na czas konieczny do zdefiniowania list kontroli dostępu dla każdego pliku i użytkownika, zdefiniowaliśmy uprawnienia tylko dla jednego z nich. Teraz, każdy użytkownik może zostać uwierzytelniony przez IIS, a następnie wszyscy mogą podawać się za konkretnego użytkownika, dla którego zostały określone prawa dostępu. Rozwiązanie takie może zaoszczędzić nam wiele czasu.
Jeszcze innym przykładem może być sytuacja w której informacje o użytkownikach są przechowywane na innym komputerze w domenie. W takim przypadku, gdy użytkownik zostanie uwierzytelniony przez serwer, ASP.NET może wykorzystać konto użytkownika zdefiniowane na innym komputerze, które może mieć inne uprawnienia od konta użytkownika uwierzytelnionego na serwerze. Także w tym przypadku, jeden wiersz kodu pozwala ASP.NET odpowiednio przeprowadzić personifikację wszystkich uwierzytelnianych użytkowników i odpowiednio wykorzystać listy kontroli dostępu aby określić ich uprawnienia.
To nie jest ASP!
Także w tradycyjnej wersji technologii ASP są dostępne proste metody uwierzytelniania. Na przykład, IIS był w stanie uwierzytelniać użytkowników przy wykorzystaniu uwierzytelniania prostego, bazującego na skrótach oraz zintegrowanego uwierzytelniania systemu Windows. Dostępna była także możliwość stworzenia własnych mechanizmów uwierzytelniających przy użyciu Passport SDK, choć niejednokrotnie było to zadanie wymagające ogromnych nakładów czasu i pracy. Niektóre witryny wykorzystywały także rozwiązania przypominające uwierzytelnianie za pośrednictwem formularzy, lecz mechanizmy te musiały być tworzone zupełnie od podstaw.
Prawdziwą zmianą jest łatwość implementacji jaką daje ASP.NET. Mechanizmy uwierzytelniania za pośrednictwem formularzy zostały wbudowane w tę technologię, a ich wykorzystanie wymaga bardzo niewielkiego nakładu pracy. Wszystkie najważniejsze mechanizmy uwierzytelniania zostały już stworzone, a programista musi jedynie podjąć decyzję gdzie mają być weryfikowane informacje podawane przez użytkowników.
W ASP.NET zostały także uproszczone sposoby wykorzystania mechanizmów autoryzacji. Autoryzacja dostępu do plików była także dostępna w klasycznej wersji technologii ASP. Nowością jest natomiast autoryzacja dostępu do adresów URL, która stanowi duży krok na przód jeśli chodzi o kontrolę dostępu do zasobów. Duże i łatwe możliwości konfiguracji kontroli dostępu do adresów URL dają pliki web.config.
Jeśli dobrze się znasz na mechanizmach bezpieczeństwa stosowanych w tradycyjnej wersji technologii ASP, to pojęcie personifikacji nie powinno być Ci obce. Ze względu na zgodność z poprzednimi wersjami technologii, także ASP.NET wykorzystuje te same mechanizmy personifikacji.
Implementacja mechanizmów zabezpieczeń w klasycznej wersji technologii ASP niejednokrotnie wymagała wprowadzania stosownych modyfikacji w konfiguracji serwera IIS oraz sytemu operacyjnego bezpośrednio na serwerze; oczywiście konieczne było posiadanie odpowiednich uprawnień administracyjnych. W ASP.NET nie jest to już konieczne — dzięki wykorzystaniu plików konfiguracyjnych web.config programista może modyfikować ustawienia aplikacji działającej na dowolnym serwerze, nie ruszając się do swego biurka.
System zabezpieczeń dostępny w technologii ASP.NET został zaprojektowany w taki sposób, aby maksymalnie ułatwić implementację zabezpieczeń w tworzonych aplikacjach, a jednocześnie zapewnić bardzo wysoki poziom bezpieczeństwa. Wszystkie mechanizmy dostępne w klasycznej wersji ASP wciąż są dostępne, a nowe rozwiązania zapewniają łatwość implementacji.
2 Część I ♦ Podstawy obsługi systemu WhizBang (Nagłówek strony)
2 Dokument2
To co jest w oryginale to na pewno nie jest w Win2000!! Odpowiednio zmieniłem tekst do końca tej części rozdziału.
Następne zdanie pomijam bo bonus chapters nie są tłumaczone
Autorowi chyba się pomyliły numery listingów, na listingu 21.3 jest strona ASP.NET a nie kod pliku konfiguracyjnego.