Walidacja poświadczeń użytkownika względem magazynu użytkowników członkostwa (C#)

Autor: Scott Mitchell

Uwaga

Ponieważ ten artykuł został napisany, dostawcy ASP.NET członkostwa zostały zastąpione przez usługę ASP.NET Identity. Zdecydowanie zalecamy aktualizowanie aplikacji w celu korzystania z platformy ASP.NET Identity , a nie dostawców członkostwa opisanych w tym artykule. ASP.NET Identity ma wiele zalet w systemie członkostwa ASP.NET, w tym :

  • Lepsza wydajność
  • Ulepszona rozszerzalność i możliwość testowania
  • Obsługa uwierzytelniania OAuth, OpenID Connect i uwierzytelniania dwuskładnikowego
  • Obsługa tożsamości opartej na oświadczeniach
  • Lepsza współdziałanie z platformą ASP.Net Core

Pobierz kod lub pobierz plik PDF

W tym samouczku sprawdzimy, jak zweryfikować poświadczenia użytkownika w magazynie użytkowników członkostwa przy użyciu zarówno środków programowych, jak i kontrolki Logowania. Przyjrzymy się również sposobom dostosowywania wyglądu i zachowania kontrolki logowania.

Wprowadzenie

W poprzednim samouczku przyjrzeliśmy się, jak utworzyć nowe konto użytkownika w strukturze członkostwa. Najpierw przyjrzeliśmy się programowe tworzeniu kont użytkowników za pomocą Membership metody klasy CreateUser , a następnie zbadaliśmy przy użyciu kontrolki CreateUserWizard Web. Jednak strona logowania obecnie weryfikuje podane poświadczenia względem trwale zakodowanej listy par nazwy użytkownika i hasła. Musimy zaktualizować logikę strony logowania, aby zweryfikować poświadczenia względem magazynu użytkowników platformy członkostwa.

Podobnie jak w przypadku tworzenia kont użytkowników, poświadczenia można zweryfikować programowo lub deklaratywnie. Interfejs API członkostwa zawiera metodę programowego weryfikowania poświadczeń użytkownika w magazynie użytkowników. A ASP.NET jest dostarczany z kontrolką Logowania w sieci Web, która renderuje interfejs użytkownika z polami tekstowymi dla nazwy użytkownika i hasła oraz przycisku w celu zalogowania się.

W tym samouczku sprawdzimy, jak zweryfikować poświadczenia użytkownika w magazynie użytkowników członkostwa przy użyciu zarówno środków programowych, jak i kontrolki Logowania. Przyjrzymy się również sposobom dostosowywania wyglądu i zachowania kontrolki logowania. Zaczynamy!

Krok 1. Weryfikowanie poświadczeń względem magazynu użytkowników członkostwa

W przypadku witryn internetowych korzystających z uwierzytelniania formularzy użytkownik loguje się do witryny internetowej, odwiedzając stronę logowania i wprowadzając swoje poświadczenia. Te poświadczenia są następnie porównywane z magazynem użytkowników. Jeśli są one prawidłowe, użytkownik otrzymuje bilet uwierzytelniania formularzy, który jest tokenem zabezpieczającym wskazującym tożsamość i autentyczność osoby odwiedzającej.

Aby zweryfikować użytkownika względem struktury członkostwa, użyj Membership metody klasy ValidateUser. Metoda ValidateUser przyjmuje dwa parametry wejściowe — username i password — i zwraca wartość logiczną wskazującą, czy poświadczenia były prawidłowe. Podobnie jak w przypadku metody badanej CreateUser w poprzednim samouczku ValidateUser metoda deleguje rzeczywistą walidację do skonfigurowanego dostawcy członkostwa.

Element SqlMembershipProvider weryfikuje podane poświadczenia, uzyskując hasło określonego użytkownika za pośrednictwem aspnet_Membership_GetPasswordWithFormat procedury składowanej. Pamiętaj, że SqlMembershipProvider hasła użytkowników są przechowywane w jednym z trzech formatów: wyczyść, zaszyfrowane lub skróty. Procedura aspnet_Membership_GetPasswordWithFormat składowana zwraca hasło w formacie nieprzetworzonym. W przypadku zaszyfrowanych lub skrótów SqlMembershipProvider haseł przekształca password wartość przekazaną do metody w ValidateUser odpowiedni stan zaszyfrowany lub skrót, a następnie porównuje je z wartością zwróconą z bazy danych. Jeśli hasło przechowywane w bazie danych pasuje do sformatowanego hasła wprowadzonego przez użytkownika, poświadczenia są prawidłowe.

Zaktualizujmy naszą stronę logowania (~/Login.aspx), aby zweryfikować podane poświadczenia względem magazynu użytkowników platformy członkostwa. Utworzyliśmy tę stronę logowania z powrotem w samouczku Omówienie uwierzytelniania formularzy, tworząc interfejs z dwoma polami TextBoxes dla nazwy użytkownika i hasła, pole wyboru Zapamiętaj mnie i przycisk Logowania (zobacz Rysunek 1). Kod weryfikuje wprowadzone poświadczenia względem trwale zakodowanej listy par nazwy użytkownika i hasła (Scott/password, Jisun/password i Sam/password).

Interfejs strony logowania zawiera dwa pola tekstowe, CheckBoxList i przycisk

Rysunek 1. Interfejs strony logowania zawiera dwa pola tekstowe, CheckBoxList i przycisk (kliknij, aby wyświetlić obraz pełnowymiarowy)

Interfejs użytkownika strony logowania może pozostać niezmieniony, ale musimy zastąpić procedurę obsługi zdarzeń przycisku Click Logowania kodem, który weryfikuje użytkownika w magazynie użytkowników platformy członkostwa. Zaktualizuj procedurę obsługi zdarzeń, aby jego kod był wyświetlany w następujący sposób:

protected void LoginButton_Click(object sender, EventArgs e)
{
    // Validate the user against the Membership framework user store
    if (Membership.ValidateUser(UserName.Text, Password.Text))
    {
        // Log the user into the site
        FormsAuthentication.RedirectFromLoginPage(UserName.Text, RememberMe.Checked);
    }
    // If we reach here, the user's credentials were invalid
    InvalidCredentialsMessage.Visible = true;
}

Ten kod jest niezwykle prosty. Zaczynamy od wywołania Membership.ValidateUser metody , przekazując dostarczoną nazwę użytkownika i hasło. Jeśli ta metoda zwróci wartość true, użytkownik jest zalogowany do witryny za pośrednictwem FormsAuthentication metody RedirectFromLoginPage klasy. (Jak omówiono w dokumencie Samouczek Omówienie uwierzytelniania formularzy , który FormsAuthentication.RedirectFromLoginPage tworzy bilet uwierzytelniania formularzy, a następnie przekierowuje użytkownika do odpowiedniej strony). Jeśli jednak poświadczenia są nieprawidłowe, InvalidCredentialsMessage zostanie wyświetlona etykieta, informując użytkownika o nieprawidłowej nazwie użytkownika lub haśle.

To wszystko!

Aby przetestować, czy strona logowania działa zgodnie z oczekiwaniami, spróbuj zalogować się przy użyciu jednego z kont użytkowników utworzonych w poprzednim samouczku. Jeśli nie utworzono jeszcze konta, utwórz je z ~/Membership/CreatingUserAccounts.aspx poziomu strony.

Uwaga

Gdy użytkownik wprowadza swoje poświadczenia i przesyła formularz strony logowania, poświadczenia, w tym hasło, są przesyłane przez Internet do serwera internetowego w postaci zwykłego tekstu. Oznacza to, że każdy haker wąchając ruch sieciowy może zobaczyć nazwę użytkownika i hasło. Aby temu zapobiec, należy zaszyfrować ruch sieciowy przy użyciu protokołu Secure Socket Layer (SSL). Zapewni to szyfrowanie poświadczeń (a także znaczników HTML całej strony) od momentu opuszczenia przeglądarki do momentu odebrania ich przez serwer internetowy.

Jak struktura członkostwa obsługuje nieprawidłowe próby logowania

Gdy użytkownik osiągnie stronę logowania i prześle swoje poświadczenia, przeglądarka wysyła żądanie HTTP do strony logowania. Jeśli poświadczenia są prawidłowe, odpowiedź HTTP zawiera bilet uwierzytelniania w pliku cookie. W związku z tym haker próbujący włamać się do witryny może utworzyć program, który wyczerpująco wysyła żądania HTTP do strony logowania z prawidłową nazwą użytkownika i odgadnięciem hasła. Jeśli hasło jest poprawne, strona logowania zwróci plik cookie biletu uwierzytelniania, w którym program wie, że natknął się na prawidłową parę nazwy użytkownika/hasła. Poprzez siłę, taki program może być w stanie natknąć się na hasło użytkownika, zwłaszcza jeśli hasło jest słabe.

Aby zapobiec takim atakom siłowym, struktura członkostwa blokuje użytkownika, jeśli w określonym przedziale czasu istnieje pewna liczba nieudanych prób logowania. Dokładne parametry można konfigurować za pomocą następujących dwóch ustawień konfiguracji dostawcy członkostwa:

  • maxInvalidPasswordAttempts — określa, ile nieprawidłowych prób hasła jest dozwolonych dla użytkownika w przedziale czasu przed zablokowaniem konta. Wartość domyślna to 5.
  • passwordAttemptWindow — wskazuje okres w minutach, w których określona liczba nieprawidłowych prób logowania spowoduje zablokowanie konta. Wartość domyślna to 10.

Jeśli użytkownik został zablokowany, nie może zalogować się, dopóki administrator nie odblokuje swojego konta. Gdy użytkownik zostanie zablokowany, ValidateUser metoda zawsze zwróci falsewartość , nawet jeśli podano prawidłowe poświadczenia. Chociaż to zachowanie zmniejsza prawdopodobieństwo, że haker włamie się do witryny poprzez metody siłowe, może to spowodować zablokowanie prawidłowego użytkownika, który po prostu zapomniał hasła lub przypadkowo ma blokadę Caps Lock lub ma zły dzień pisania.

Niestety nie ma wbudowanego narzędzia do odblokowywania konta użytkownika. Aby odblokować konto, możesz bezpośrednio zmodyfikować bazę danych — zmienić IsLockedOut pole w aspnet_Membership tabeli dla odpowiedniego konta użytkownika — lub utworzyć interfejs internetowy, który wyświetla listę zablokowanych kont z opcjami ich odblokowania. Przeanalizujemy tworzenie interfejsów administracyjnych na potrzeby wykonywania typowych zadań związanych z kontem użytkownika i rolami w przyszłym samouczku.

Uwaga

Jedną z wad ValidateUser metody jest to, że gdy podane poświadczenia są nieprawidłowe, nie podaje żadnego wyjaśnienia, dlaczego. Poświadczenia mogą być nieprawidłowe, ponieważ nie ma pasującej pary nazwy użytkownika/hasła w magazynie użytkowników lub dlatego, że użytkownik nie został jeszcze zatwierdzony lub ponieważ użytkownik został zablokowany. W kroku 4 zobaczymy, jak wyświetlić użytkownikowi bardziej szczegółowy komunikat, gdy próba logowania zakończy się niepowodzeniem.

Krok 2. Zbieranie poświadczeń za pomocą kontrolki internetowej logowania

Kontrolka Login Web renderuje domyślny interfejs użytkownika bardzo podobny do interfejsu utworzonego z powrotem w samouczku Omówienie uwierzytelniania formularzy. Użycie kontrolki Logowania pozwala nam na utworzenie interfejsu w celu zbierania poświadczeń gościa. Ponadto kontrolka Logowania automatycznie loguje się do użytkownika (przy założeniu, że przesłane poświadczenia są prawidłowe), co pozwala zaoszczędzić nam konieczność pisania dowolnego kodu.

Zaktualizujmy Login.aspxelement , zastępując ręcznie utworzony interfejs i kod kontrolką Login. Zacznij od usunięcia istniejącego znaczników i kodu w pliku Login.aspx. Możesz go usunąć wprost lub po prostu skomentować. Aby oznaczyć znaczniki deklaratywne jako komentarz, umieść je z ogranicznikami <%-- i --%> . Możesz wprowadzić te ograniczniki ręcznie lub, jak pokazano na rysunku 2, możesz wybrać tekst do komentarza, a następnie kliknąć ikonę Komentarz zaznaczonych wierszy na pasku narzędzi. Podobnie możesz użyć ikony Komentarz zaznaczonych wierszy, aby oznaczyć wybrany kod w klasie za kodem.

Oznacz jako komentarz istniejący deklaratywny znacznik i kod źródłowy w pliku Login.aspx

Rysunek 2. Oznacz istniejące znaczniki deklaratywne i kod źródłowy w programie Login.aspx (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Ikona Komentarz zaznaczonych wierszy nie jest dostępna podczas wyświetlania znaczników deklaratywnych w programie Visual Studio 2005. Jeśli nie używasz programu Visual Studio 2008, musisz ręcznie dodać <%-- ograniczniki i --%> .

Następnie przeciągnij kontrolkę Login z przybornika na stronę i ustaw jej ID właściwość na myLogin. Na tym etapie ekran powinien wyglądać podobnie do rysunku 3. Należy pamiętać, że domyślny interfejs kontrolki Login zawiera kontrolki TextBox dla nazwy użytkownika i hasła, zapamiętaj mnie przy następnym checkboxie i przycisk logowania. Istnieją również RequiredFieldValidator kontrolki dla dwóch pola TextBoxes.

Dodawanie kontrolki logowania do strony

Rysunek 3. Dodawanie kontrolki logowania do strony (kliknij, aby wyświetlić obraz pełnowymiarowy)

I gotowe! Po kliknięciu przycisku Zaloguj się kontrolki Logowania nastąpi powrót, a kontrolka Login wywoła metodę Membership.ValidateUser , przekazując wprowadzoną nazwę użytkownika i hasło. Jeśli poświadczenia są nieprawidłowe, kontrolka Logowania wyświetla komunikat informujący o tym. Jeśli jednak poświadczenia są prawidłowe, kontrolka Logowanie tworzy bilet uwierzytelniania formularzy i przekierowuje użytkownika do odpowiedniej strony.

Kontrolka Logowania używa czterech czynników do określenia odpowiedniej strony w celu przekierowania użytkownika do po pomyślnym zalogowaniu:

  • Określa, czy kontrolka Logowania znajduje się na stronie logowania zgodnie z definicją w loginUrl konfiguracji uwierzytelniania formularzy; wartość domyślna tego ustawienia to Login.aspx
  • Obecność parametru ReturnUrl querystring
  • Wartość właściwości kontrolki DestinationUrl Login
  • Wartość określona defaultUrl w ustawieniach konfiguracji uwierzytelniania formularzy; wartość domyślna tego ustawienia to Default.aspx

Rysunek 4 przedstawia sposób, w jaki kontrolka Logowania używa tych czterech parametrów do podjęcia odpowiedniej decyzji dotyczącej strony.

Kontrolka Login używa czterech parametrów, aby uzyskać odpowiednią decyzję o stronie.

Rysunek 4. Dodawanie kontrolki logowania do strony (kliknij, aby wyświetlić obraz pełnowymiarowy)

Poświęć chwilę na przetestowanie kontrolki Logowania, odwiedzając witrynę za pośrednictwem przeglądarki i logując się jako istniejący użytkownik w strukturze członkostwa.

Interfejs renderowany kontrolki Logowania jest wysoce konfigurowalny. Istnieje wiele właściwości, które mają wpływ na jego wygląd; Co więcej, kontrolkę Login można przekonwertować na szablon umożliwiający precyzyjną kontrolę nad układem elementów interfejsu użytkownika. W pozostałej części tego kroku dowiesz się, jak dostosować wygląd i układ.

Dostosowywanie wyglądu kontrolki logowania

Domyślne ustawienia właściwości kontrolki Logowania renderują interfejs użytkownika z tytułem (Log In), kontrolkami TextBox i Label dla danych wejściowych nazwy użytkownika i hasła, kontrolki Zapamiętaj mnie przy następnym uruchomieniu Pola wyboru i przycisku Zaloguj. Wygląd tych elementów można skonfigurować za pomocą wielu właściwości kontrolki Logowania. Ponadto dodatkowe elementy interfejsu użytkownika — takie jak link do strony w celu utworzenia nowego konta użytkownika — można dodać, ustawiając właściwość lub dwie.

Poświęćmy chwilę na pojawienie się naszej kontrolki Logowania. Login.aspx Ponieważ strona ma już tekst w górnej części strony z napisem Login, tytuł kontrolki Logowania jest zbędny. W związku z tym usuń TitleText wartość właściwości , aby usunąć tytuł kontrolki Logowania.

Nazwa użytkownika: i Hasło: etykiety po lewej stronie dwóch kontrolek TextBox można dostosować odpowiednio za pomocą UserNameLabelText właściwości i PasswordLabelText. Zmieńmy nazwę użytkownika: Etykieta, aby odczytać nazwę użytkownika:. Style Etykieta i Pole tekstowe można konfigurować odpowiednio za pomocą LabelStyle właściwości i TextBoxStyle.

Właściwość Remember me next time CheckBox's Text (Zapamiętaj mnie) można ustawić za pomocą kontrolki RememberMeText propertyLogin , a jej domyślny stan sprawdzania można skonfigurować za pośrednictwem elementu RememberMeSet property (domyślnie ma wartość False). Przejdź dalej i ustaw RememberMeSet właściwość Na wartość True, aby pole wyboru Zapamiętaj mnie następnym razem było domyślnie zaznaczone.

Kontrolka Login oferuje dwie właściwości służące do dostosowywania układu kontrolek interfejsu użytkownika. Wskazuje TextLayout property , czy pola Nazwa użytkownika: i Hasło: etykiety są wyświetlane po lewej stronie odpowiadających im pól TextBoxes (wartość domyślna) lub powyżej nich. Wskazuje Orientation property , czy dane wejściowe nazwy użytkownika i hasła znajdują się w pionie (jeden powyżej drugiego) czy w poziomie. Pozostawię te dwie właściwości ustawione na ich wartości domyślne, ale zachęcam do wypróbowania tych dwóch właściwości do ich wartości innych niż domyślne, aby zobaczyć wynikowy efekt.

Uwaga

W następnej sekcji Konfigurowanie układu kontrolki logowania przyjrzymy się używaniu szablonów do definiowania dokładnego układu elementów interfejsu użytkownika kontrolki Układ.

Podsumuj ustawienia właściwości kontrolki Logowania, ustawiając właściwości i CreateUserUrl na CreateUserText Niezarejestrowane jeszcze? Utwórz konto! i ~/Membership/CreatingUserAccounts.aspx, odpowiednio. Spowoduje to dodanie hiperlinku do interfejsu kontrolki Logowania wskazującego stronę utworzoną w poprzednim samouczku. Właściwości i HelpPageUrlPasswordRecoveryTextPasswordRecoveryUrl właściwości kontrolki HelpPageText Logowania działają w taki sam sposób, renderowanie linków do strony pomocy i strony odzyskiwania hasła.

Po wprowadzeniu tych zmian właściwości znaczniki deklaratywne i wygląd kontrolki Logowania powinny wyglądać podobnie do przedstawionego na rysunku 5.

Wartości właściwości kontrolki logowania dyktują jej wygląd

Rysunek 5. Wartości właściwości kontrolki logowania określają jego wygląd (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Konfigurowanie układu kontrolki logowania

Domyślny interfejs użytkownika kontrolki Login Web określa interfejs w kodzie HTML <table>. Ale co zrobić, jeśli potrzebujemy bardziej precyzyjnej kontroli nad renderowanych danych wyjściowych? Może chcemy zastąpić element <table> serią tagów <div> . A co zrobić, jeśli nasza aplikacja wymaga dodatkowych poświadczeń do uwierzytelniania? Wiele finansowych witryn internetowych, na przykład, wymaga od użytkowników podania nie tylko nazwy użytkownika i hasła, ale także osobistego numeru identyfikacyjnego (PIN) lub innych informacji identyfikacyjnych. Niezależnie od przyczyn, można przekonwertować kontrolkę Logowania na szablon, z którego możemy jawnie zdefiniować deklaratywne znaczniki interfejsu.

Musimy wykonać dwie czynności, aby zaktualizować kontrolkę Logowania w celu zebrania dodatkowych poświadczeń:

  1. Zaktualizuj interfejs kontrolki Logowania, aby uwzględnić kontrolki sieci Web w celu zbierania dodatkowych poświadczeń.
  2. Zastąp wewnętrzną logikę uwierzytelniania kontrolki Logowania, aby użytkownik był uwierzytelniany tylko wtedy, gdy jego nazwa użytkownika i hasło są prawidłowe, a ich dodatkowe poświadczenia również są prawidłowe.

Aby wykonać pierwsze zadanie, musimy przekonwertować kontrolkę Logowania na szablon i dodać niezbędne kontrolki sieci Web. Jeśli chodzi o drugie zadanie, logika uwierzytelniania kontrolki Logowania może zostać zastąpiona przez utworzenie programu obsługi zdarzeń dla zdarzenia kontrolkiAuthenticate.

Zaktualizujmy kontrolkę Logowanie, aby monitowali użytkowników o podanie nazwy użytkownika, hasła i adresu e-mail oraz uwierzytelniają użytkownika tylko wtedy, gdy podany adres e-mail jest zgodny z ich adresem e-mail w pliku. Najpierw musimy przekonwertować interfejs kontrolki Logowania na szablon. Z tagu inteligentnego kontrolki Logowania wybierz opcję Konwertuj na szablon.

Konwertowanie kontrolki logowania na szablon

Rysunek 6. Konwertowanie kontrolki logowania na szablon (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Uwaga

Aby przywrócić kontrolkę Logowanie do jej wersji wstępnej szablonu, kliknij link Resetuj z tagu inteligentnego kontrolki.

Konwertowanie kontrolki Login na szablon powoduje dodanie LayoutTemplate elementu do deklaratywnego narzutu kontrolki z elementami HTML i kontrolkami sieci Web definiującymi interfejs użytkownika. Jak pokazano na rysunku 7, konwertowanie kontrolki na szablon usuwa wiele właściwości z okno Właściwości, takich jak TitleText, CreateUserUrli tak dalej, ponieważ te wartości właściwości są ignorowane podczas korzystania z szablonu.

Mniej właściwości jest dostępnych, gdy kontrolka logowania jest konwertowana na szablon

Rysunek 7. Mniejsza liczba właściwości jest dostępna, gdy kontrolka logowania jest konwertowana na szablon (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Znaczniki HTML w pliku LayoutTemplate mogą być modyfikowane zgodnie z potrzebami. Podobnie możesz dodać nowe kontrolki sieci Web do szablonu. Jednak ważne jest, aby podstawowe kontrolki sieci Web kontrolki logowania pozostały w szablonie i zachowały przypisane ID wartości. W szczególności nie usuwaj ani nie zmieniaj nazw UserName ani Password textBoxes, RememberMe CheckBox, LoginButton Button, FailureText Label ani RequiredFieldValidator kontrolek.

Aby zebrać adres e-mail osoby odwiedzającej, musimy dodać element TextBox do szablonu. Dodaj następujące znaczniki deklaratywne między wierszem tabeli (<tr>), który zawiera kontrolkę Password TextBox i wiersz tabeli, który przechowuje pole wyboru Zapamiętaj mnie następnym razem:

<tr>
 <td align="right">
 <asp:Label ID="EmailLabel" runat="server" AssociatedControlID="Email">Email:</asp:Label>
 </td>
 <td>
 <asp:TextBox ID="Email" runat="server"></asp:TextBox>
 <asp:RequiredFieldValidator ID="EmailRequired" runat="server" 
 ControlToValidate="Email" ErrorMessage="Email is required." 
 ToolTip="Email is required." ValidationGroup="myLogin">*</asp:RequiredFieldValidator>
 </td>
</tr>

Po dodaniu kontrolki Email TextBox odwiedź stronę za pośrednictwem przeglądarki. Jak pokazano na rysunku 8, interfejs użytkownika kontrolki Logowania zawiera teraz trzecie pole tekstowe.

Kontrolka logowania zawiera teraz pole tekstowe adresu Email użytkownika

Rysunek 8. Kontrolka logowania zawiera teraz pole tekstowe adresu Email użytkownika (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

W tym momencie kontrolka Logowania nadal używa Membership.ValidateUser metody do weryfikowania podanych poświadczeń. W związku z tym wartość wprowadzona do kontrolki Email TextBox nie ma wpływu na to, czy użytkownik może się zalogować. W kroku 3 przyjrzymy się, jak zastąpić logikę uwierzytelniania kontrolki Logowania, tak aby poświadczenia zostały uznane za prawidłowe tylko wtedy, gdy nazwa użytkownika i hasło są prawidłowe, a podany adres e-mail jest zgodny z adresem e-mail w pliku.

Krok 3. Modyfikowanie logiki uwierzytelniania kontrolki logowania

Gdy gość dostarczy swoje poświadczenia i kliknie przycisk Zaloguj, zostanie wyświetlony komunikat zwrotny, a kontrolka Logowania przechodzi przez przepływ pracy uwierzytelniania. Przepływ pracy rozpoczyna się od podniesienia LoggingIn zdarzenia. Wszelkie procedury obsługi zdarzeń skojarzone z tym zdarzeniem mogą anulować operację logowania, ustawiając e.Cancel właściwość na true.

Jeśli operacja logowania nie zostanie anulowana, przepływ pracy postępuje, wywołując Authenticate zdarzenie. Jeśli istnieje procedura obsługi zdarzeń dla Authenticate zdarzenia, odpowiada za określenie, czy podane poświadczenia są prawidłowe, czy nie. Jeśli program obsługi zdarzeń nie zostanie określony, kontrolka Logowania używa Membership.ValidateUser metody w celu określenia ważności poświadczeń.

Jeśli podane poświadczenia są prawidłowe, zostanie utworzony bilet uwierzytelniania formularzy, LoggedIn zostanie zgłoszone zdarzenie , a użytkownik zostanie przekierowany do odpowiedniej strony. Jeśli jednak poświadczenia zostaną uznane za nieprawidłowe, LoginError zostanie zgłoszone zdarzenie i zostanie wyświetlony komunikat informujący użytkownika o nieprawidłowych poświadczeniach. Domyślnie po niepowodzeniu kontrolka Logowania po prostu ustawia FailureText właściwość Text kontrolki Etykieta na komunikat o niepowodzeniu ( Próba logowania nie powiodła się. Spróbuj ponownie ). Jeśli jednak właściwość kontrolki FailureAction Logowania jest ustawiona na RedirectToLoginPagewartość , kontrolka Logowania wystawia element na Response.Redirect stronie logowania dołączającej parametr loginfailure=1 querystring (co powoduje, że kontrolka Logowania wyświetla komunikat o błędzie).

Rysunek 9 zawiera wykres blokowy przepływu pracy uwierzytelniania.

Przepływ pracy uwierzytelniania kontrolki logowania

Rysunek 9. Przepływ pracy uwierzytelniania kontrolki logowania (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Uwaga

Jeśli zastanawiasz się, kiedy użyjesz FailureActionopcji strony , RedirectToLogin rozważ następujący scenariusz. W tej chwili nasza Site.master strona wzorcowa ma obecnie tekst Witaj, obcy wyświetlany w lewej kolumnie po odwiedzeniu przez anonimowego użytkownika, ale załóżmy, że chcemy zastąpić ten tekst kontrolką Login. Pozwoliłoby to anonimowemu użytkownikowi zalogować się z dowolnej strony w witrynie, zamiast wymagać od nich bezpośredniego odwiedzenia strony logowania. Jeśli jednak użytkownik nie mógł zalogować się za pośrednictwem kontrolki Logowania renderowanej przez stronę wzorcową, warto przekierować ich do strony logowania (Login.aspx), ponieważ ta strona prawdopodobnie zawiera dodatkowe instrukcje, linki i inne pomoc — takie jak linki do tworzenia nowego konta lub pobierania utraconego hasła — które nie zostały dodane do strony wzorcowej.

Tworzenie programu obsługi zdarzeńAuthenticate

Aby podłączyć naszą niestandardową logikę uwierzytelniania, musimy utworzyć procedurę obsługi zdarzeń dla zdarzenia kontrolki Authenticate Logowania. Utworzenie procedury obsługi zdarzeń dla zdarzenia Authenticate spowoduje wygenerowanie następującej definicji procedury obsługi zdarzeń:

protected void myLogin_Authenticate(object sender, AuthenticateEventArgs e)
{
}

Jak widać, Authenticate procedura obsługi zdarzeń jest przekazywana obiekt typu AuthenticateEventArgs jako drugi parametr wejściowy. Klasa AuthenticateEventArgs zawiera właściwość logiczną o nazwie Authenticated , która służy do określania, czy podane poświadczenia są prawidłowe. Następnie naszym zadaniem jest napisanie kodu, który określa, czy podane poświadczenia są prawidłowe, czy nie, i odpowiednio ustawić e.Authenticate właściwość.

Określanie i weryfikowanie podanych poświadczeń

Użyj właściwości i Password kontrolki UserName Logowania, aby określić poświadczenia nazwy użytkownika i hasła wprowadzone przez użytkownika. Aby określić wartości wprowadzone do dodatkowych kontrolek sieci Web (takich jak Email TextBox dodane w poprzednim kroku), użyj ("LoginControlIDcontrolID.FindControl"), aby uzyskać programowe odwołanie do kontrolki sieci Web w szablonie, którego ID właściwość jest równa .controlID Aby na przykład uzyskać odwołanie do kontrolki Email TextBox, użyj następującego kodu:

TextBox EmailTextBox = myLogin.FindControl("Email") as TextBox;

Aby zweryfikować poświadczenia użytkownika, musimy wykonać dwie czynności:

  1. Upewnij się, że podana nazwa użytkownika i hasło są prawidłowe
  2. Upewnij się, że wprowadzony adres e-mail jest zgodny z adresem e-mail w pliku, na który użytkownik próbuje się zalogować

Aby wykonać pierwsze sprawdzenie, możemy po prostu użyć Membership.ValidateUser metody, jak pokazano w kroku 1. W przypadku drugiego sprawdzenia musimy określić adres e-mail użytkownika, aby można było porównać go z adresem e-mail wprowadzonym w kontrolce TextBox. Aby uzyskać informacje o określonym użytkowniku, użyj Membership metody klasy GetUser.

Metoda GetUser ma wiele przeciążeń. Jeśli nie przekazuje żadnych parametrów, zwraca informacje o aktualnie zalogowanym użytkowniku. Aby uzyskać informacje o określonym użytkowniku, wywołaj GetUser metodę przekazywania nazwy użytkownika. Tak czy inaczej, GetUser zwraca MembershipUser obiekt, który ma właściwości, takie jak UserName, Email, IsApproved, IsOnlinei tak dalej.

Poniższy kod implementuje te dwa testy. Jeśli obie te metody są przekazywane, e.Authenticate zostanie ustawiona wartość true, w przeciwnym razie zostanie przypisana wartość false.

protected void myLogin_Authenticate(object sender, AuthenticateEventArgs e)
{
    // Get the email address entered
    TextBox EmailTextBox = myLogin.FindControl("Email") as TextBox;
    string email = EmailTextBox.Text.Trim();

    // Verify that the username/password pair is valid
    if (Membership.ValidateUser(myLogin.UserName, myLogin.Password))
    {
        // Username/password are valid, check email
        MembershipUser usrInfo = Membership.GetUser(myLogin.UserName);
        if (usrInfo != null && string.Compare(usrInfo.Email, email, true) == 0)
        {
            // Email matches, the credentials are valid
            e.Authenticated = true;
        }
        else
        {
            // Email address is invalid...
            e.Authenticated = false;
        }
    }
    else
    {
        // Username/password are not valid...
        e.Authenticated = false;
    }
}

Przy użyciu tego kodu spróbuj zalogować się jako prawidłowy użytkownik, wprowadzając prawidłową nazwę użytkownika, hasło i adres e-mail. Spróbuj ponownie, ale tym razem celowo użyj niepoprawnego adresu e-mail (zobacz Rysunek 10). Na koniec spróbuj wykonać ją po raz trzeci przy użyciu nieistniejącej nazwy użytkownika. W pierwszym przypadku powinno nastąpić pomyślne zalogowanie do witryny, ale w dwóch ostatnich przypadkach powinien zostać wyświetlony komunikat o nieprawidłowych poświadczeniach kontrolki Logowania.

Tito nie może zalogować się podczas podawania niepoprawnego adresu Email

Rysunek 10. Tito nie może zalogować się podczas podawania niepoprawnego adresu Email (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Uwaga

Zgodnie z opisem w sekcji How the Membership Framework Handles Invalid Login Attempts (Jak platforma członkostwa obsługuje nieprawidłowe próby logowania) w kroku 1, gdy Membership.ValidateUser metoda jest wywoływana i przekazuje nieprawidłowe poświadczenia, śledzi nieprawidłową próbę logowania i blokuje użytkownika, jeśli przekroczy określony próg nieprawidłowych prób w określonym przedziale czasu. Ponieważ nasza niestandardowa logika uwierzytelniania wywołuje ValidateUser metodę, nieprawidłowe hasło prawidłowej nazwy użytkownika zwiększy licznik nieprawidłowej próby logowania, ale ten licznik nie jest zwiększany w przypadku, gdy nazwa użytkownika i hasło są prawidłowe, ale adres e-mail jest niepoprawny. Istnieje prawdopodobieństwo, że to zachowanie jest odpowiednie, ponieważ jest mało prawdopodobne, aby haker znał nazwę użytkownika i hasło, ale musi użyć technik siłowych w celu określenia adresu e-mail użytkownika.

Krok 4. Ulepszanie komunikatu o nieprawidłowych poświadczeniach kontrolki logowania

Gdy użytkownik próbuje zalogować się przy użyciu nieprawidłowych poświadczeń, w kontrolce Logowania zostanie wyświetlony komunikat z informacją, że próba logowania nie powiodła się. W szczególności kontrolka wyświetla komunikat określony przez jego FailureText właściwość, która ma wartość domyślną Twojej próby logowania nie powiodła się. Spróbuj ponownie.

Pamiętaj, że istnieje wiele powodów, dla których poświadczenia użytkownika mogą być nieprawidłowe:

  • Nazwa użytkownika może nie istnieć
  • Nazwa użytkownika istnieje, ale hasło jest nieprawidłowe
  • Nazwa użytkownika i hasło są prawidłowe, ale użytkownik nie został jeszcze zatwierdzony
  • Nazwa użytkownika i hasło są prawidłowe, ale użytkownik jest zablokowany (najprawdopodobniej ponieważ przekroczył liczbę nieprawidłowych prób logowania w określonym przedziale czasu)

W przypadku używania niestandardowej logiki uwierzytelniania mogą istnieć inne przyczyny. Na przykład przy użyciu kodu napisanego w kroku 3 nazwa użytkownika i hasło mogą być prawidłowe, ale adres e-mail może być niepoprawny.

Niezależnie od tego, dlaczego poświadczenia są nieprawidłowe, kontrolka Logowania wyświetla ten sam komunikat o błędzie. Ten brak opinii może być mylący dla użytkownika, którego konto nie zostało jeszcze zatwierdzone lub który został zablokowany. Jednak przy odrobinie pracy możemy mieć kontrolkę Logowanie wyświetlać bardziej odpowiedni komunikat.

Za każdym razem, gdy użytkownik próbuje zalogować się przy użyciu nieprawidłowych poświadczeń, kontrolka Logowania zgłasza swoje LoginError zdarzenie. Utwórz procedurę obsługi zdarzeń dla tego zdarzenia i dodaj następujący kod:

protected void myLogin_LoginError(object sender, EventArgs e)
{
    // Determine why the user could not login...
    myLogin.FailureText = "Your login attempt was not successful. Please try again.";

    // Does there exist a User account for this user?
    MembershipUser usrInfo = Membership.GetUser(myLogin.UserName);
    if (usrInfo != null)
    {
        // Is this user locked out?
        if (usrInfo.IsLockedOut)
        {
            myLogin.FailureText = "Your account has been locked out because of too many invalid login attempts. Please contact the administrator to have your account unlocked.";
        }
        else if (!usrInfo.IsApproved)
        {
            myLogin.FailureText = "Your account has not yet been approved. You cannot login until an administrator has approved your account.";
        }
    }
}

Powyższy kod rozpoczyna się od ustawienia właściwości kontrolki FailureText Login na wartość domyślną ( Próba logowania nie powiodła się. Spróbuj ponownie ). Następnie sprawdza, czy podana nazwa użytkownika jest mapowana na istniejące konto użytkownika. Jeśli tak, skonsultuje się z wynikowymi MembershipUserIsLockedOut obiektami i IsApproved właściwościami, aby określić, czy konto zostało zablokowane lub nie zostało jeszcze zatwierdzone. W obu przypadkach FailureText właściwość jest aktualizowana do odpowiedniej wartości.

Aby przetestować ten kod, celowo spróbuj zalogować się jako istniejący użytkownik, ale użyj nieprawidłowego hasła. Zrób to pięć razy z rzędu w ciągu 10 minut, a konto zostanie zablokowane. Jak pokazano na rysunku 11, kolejne próby logowania zawsze kończą się niepowodzeniem (nawet przy poprawnym haśle), ale teraz będą wyświetlane bardziej opisowe Konto zostało zablokowane z powodu zbyt wielu nieprawidłowych prób logowania. Skontaktuj się z administratorem, aby mieć odblokowane konto.

Tito wykonał zbyt wiele nieprawidłowych prób logowania i został zablokowany

Rysunek 11. Tito wykonał zbyt wiele nieprawidłowych prób logowania i został zablokowany (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Podsumowanie

Przed tym samouczkiem nasza strona logowania zweryfikowała podane poświadczenia względem zakodowanej listy par nazwy użytkownika/hasła. W tym samouczku zaktualizowaliśmy stronę w celu zweryfikowania poświadczeń w strukturze członkostwa. W kroku 1 przyjrzeliśmy się programistycznej metodzie Membership.ValidateUser . W kroku 2 zastąpiliśmy ręcznie utworzony interfejs użytkownika i kod kontrolką Logowanie.

Kontrolka Logowanie renderuje standardowy interfejs użytkownika logowania i automatycznie weryfikuje poświadczenia użytkownika względem struktury członkostwa. Ponadto w przypadku prawidłowych poświadczeń kontrolka Logowania podpisuje użytkownika za pomocą uwierzytelniania formularzy. Krótko mówiąc, dostępne jest w pełni funkcjonalne środowisko użytkownika logowania, przeciągając kontrolkę Logowania na stronę, bez dodatkowego deklaratywnego narzutu ani kodu. Co więcej, kontrolka Logowania jest wysoce dostosowywalna, co pozwala na uzyskanie dokładnego stopnia kontroli zarówno nad renderowany interfejs użytkownika, jak i logiką uwierzytelniania.

W tym momencie odwiedzający naszą witrynę internetową mogą utworzyć nowe konto użytkownika i zalogować się do witryny, ale musimy jeszcze przyjrzeć się ograniczeniu dostępu do stron na podstawie uwierzytelnionego użytkownika. Obecnie każdy użytkownik, uwierzytelniony lub anonimowy, może wyświetlić dowolną stronę w naszej witrynie. Oprócz kontrolowania dostępu do stron naszej witryny na podstawie użytkownika możemy mieć pewne strony, których funkcjonalność zależy od użytkownika. W następnym samouczku przedstawiono sposób ograniczania dostępu i funkcji na stronie na podstawie zalogowanego użytkownika.

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. Głównymi recenzentami tego samouczka byli Teresa Murphy i Michael Olivero. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.