Implementowanie uwierzytelniania opartego na formularzach w aplikacji ASP.NET przy użyciu języka C#.NET

W tym artykule pokazano, jak zaimplementować uwierzytelnianie oparte na formularzach przy użyciu bazy danych do przechowywania użytkowników. Odnosi się on do następujących przestrzeni nazw biblioteki klas microsoft .NET Framework:

  • System.Data.SqlClient
  • System.Web.Security

Oryginalna wersja produktu: ASP.NET
Oryginalny numer KB: 301240

Wymagania

Na poniższej liście przedstawiono zalecany sprzęt, oprogramowanie, infrastrukturę sieciową i dodatki Service Pack, których potrzebujesz:

  • Visual Studio .NET
  • Internet Information Services (IIS) w wersji 5.0 lub nowszej
  • SQL Server

Tworzenie aplikacji ASP.NET przy użyciu platformy .NET języka C#

  1. Otwórz program Visual Studio .NET.
  2. Utwórz nową aplikację internetową ASP.NET i określ nazwę i lokalizację.

Konfigurowanie ustawień zabezpieczeń w pliku Web.config

W tej sekcji przedstawiono sposób dodawania i modyfikowania <authentication> sekcji konfiguracji i <authorization> w celu skonfigurowania aplikacji ASP.NET do korzystania z uwierzytelniania opartego na formularzach.

  1. W Eksplorator rozwiązań otwórz plik Web.config.

  2. Zmień tryb uwierzytelniania na Formularze.

  3. <Forms> Wstaw tag i wypełnij odpowiednie atrybuty. Skopiuj następujący kod, a następnie wybierz pozycję Wklej jako kod HTML w menu Edycja , aby wkleić kod w <authentication> sekcji pliku:

    <authentication mode="Forms">
        <forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx"
            protection="All" path="/" timeout="30" />
    </authentication>
    
  4. Odmowa dostępu do anonimowego użytkownika w sekcji w <authorization> następujący sposób:

    <authorization>
        <deny users ="?" />
        <allow users = "*" />
    </authorization>
    

Tworzenie przykładowej tabeli bazy danych do przechowywania szczegółów użytkowników

W tej sekcji przedstawiono sposób tworzenia przykładowej bazy danych do przechowywania nazwy użytkownika, hasła i roli dla użytkowników. Kolumna roli jest potrzebna, jeśli chcesz przechowywać role użytkowników w bazie danych i implementować zabezpieczenia oparte na rolach.

  1. W menu Start wybierz pozycję Uruchom, a następnie wpisz Notatnik, aby otworzyć Notatnik.

  2. Wyróżnij następujący kod skryptu SQL, kliknij prawym przyciskiem myszy kod, a następnie wybierz pozycję Kopiuj. W Notatniku wybierz pozycję Wklej w menu Edycja , aby wkleić następujący kod:

    if exists (select * from sysobjects where id =
    object_id(N'[dbo].[Users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
        drop table [dbo].[Users]
    GO
    CREATE TABLE [dbo].[Users] ([uname] [varchar] (15) NOT NULL,
        [Pwd] [varchar] (25) NOT NULL,
        [userRole] [varchar] (25) NOT NULL,
    ) ON [PRIMARY]
    GO
    ALTER TABLE [dbo].[Users] WITH NOCHECK ADD
        CONSTRAINT [PK_Users] PRIMARY KEY NONCLUSTERED
        ([uname]
        ) ON [PRIMARY]
    GO
    
    INSERT INTO Users values('user1','user1','Manager')
    INSERT INTO Users values('user2','user2','Admin')
    INSERT INTO Users values('user3','user3','User')
    GO
    
  3. Zapisz plik jako Users.sql.

  4. Na komputerze SQL Server otwórz Users.sql w analizatorze zapytań. Z listy baz danych wybierz puby i uruchom skrypt. Ta operacja tworzy przykładową tabelę użytkowników i wypełnia tabelę w bazie danych pubów, która ma być używana z tą przykładową aplikacją.

Tworzenie strony Logon.aspx

  1. Dodaj nowy formularz internetowy do projektu o nazwie Logon.aspx.

  2. Otwórz stronę Logon.aspx w edytorze i przejdź do widoku HTML.

  3. Skopiuj następujący kod i użyj opcji Wklej jako HTML w menu Edycja , aby wstawić kod między tagami <form> :

    <h3>
        <font face="Verdana">Logon Page</font>
    </h3>
    <table>
        <tr>
            <td>Email:</td>
            <td><input id="txtUserName" type="text" runat="server"></td>
            <td><ASP:RequiredFieldValidator ControlToValidate="txtUserName"
                Display="Static" ErrorMessage="*" runat="server" 
                ID="vUserName" /></td>
        </tr>
        <tr>
            <td>Password:</td>
            <td><input id="txtUserPass" type="password" runat="server"></td>
            <td><ASP:RequiredFieldValidator ControlToValidate="txtUserPass"
            Display="Static" ErrorMessage="*" runat="server"
            ID="vUserPass" />
            </td>
        </tr>
        <tr>
            <td>Persistent Cookie:</td>
            <td><ASP:CheckBox id="chkPersistCookie" runat="server" autopostback="false" /></td>
            <td></td>
        </tr>
    </table>
    <input type="submit" Value="Logon" runat="server" ID="cmdLogin"><p></p>
    <asp:Label id="lblMsg" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat="server" />
    

    Ten formularz sieci Web służy do prezentowania użytkownikom formularza logowania, aby mogli podać nazwę użytkownika i hasło, aby zalogować się do aplikacji.

  4. Przejdź do widoku projektu i zapisz stronę.

Kodowanie procedury obsługi zdarzeń w celu zweryfikowania poświadczeń użytkownika

W tej sekcji przedstawiono kod umieszczony na stronie za kodem (Logon.aspx.cs).

  1. Kliknij dwukrotnie pozycję Zaloguj , aby otworzyć plik Logon.aspx.cs .

  2. Zaimportuj wymagane przestrzenie nazw do pliku za kodem:

    using System.Data.SqlClient;
    using System.Web.Security;
    
  3. Utwórz funkcję ValidateUser w celu zweryfikowania poświadczeń użytkownika, przeglądając bazę danych. Upewnij się, że ciąg został zmieniony tak Connection , aby wskazywał bazę danych.

    private bool ValidateUser( string userName, string passWord )
    {
        SqlConnection conn;
        SqlCommand cmd;
        string lookupPassword = null;
    
        // Check for invalid userName.
        // userName must not be null and must be between 1 and 15 characters.
        if ( ( null == userName ) || ( 0 == userName.Length ) || ( userName.Length > 15 ))
        {
            System.Diagnostics.Trace.WriteLine( "[ValidateUser] Input validation of userName failed." );
            return false;
        }
    
        // Check for invalid passWord.
        // passWord must not be null and must be between 1 and 25 characters.
        if ( ( null == passWord ) || ( 0 == passWord.Length ) || ( passWord.Length > 25 ))
        {
            System.Diagnostics.Trace.WriteLine( "[ValidateUser] Input validation of passWord failed." );
            return false;
        }
    
        try
        {
            // Consult with your SQL Server administrator for an appropriate connection
            // string to use to connect to your local SQL Server.
            conn = new SqlConnection( "server=localhost;Integrated Security=SSPI;database=pubs" );
            conn.Open();
    
            // Create SqlCommand to select pwd field from users table given supplied userName.
            cmd = new SqlCommand( "Select pwd from users where uname=@userName", conn );
            cmd.Parameters.Add( "@userName", SqlDbType.VarChar, 25 );
            cmd.Parameters["@userName"].Value = userName;
    
            // Execute command and fetch pwd field into lookupPassword string.
            lookupPassword = (string) cmd.ExecuteScalar();
    
            // Cleanup command and connection objects.
            cmd.Dispose();
            conn.Dispose();
        }
        catch ( Exception ex )
        {
            // Add error handling here for debugging.
            // This error message should not be sent back to the caller.
            System.Diagnostics.Trace.WriteLine( "[ValidateUser] Exception " + ex.Message );
        }
    
        // If no password found, return false.
        if ( null == lookupPassword )
        {
            // You could write failed login attempts here to event log for additional security.
            return false;
        }
    
        // Compare lookupPassword and input passWord, using a case-sensitive comparison.
        return ( 0 == string.Compare( lookupPassword, passWord, false ));
    }
    
  4. Możesz użyć jednej z dwóch metod, aby wygenerować plik cookie uwierzytelniania formularzy i przekierować użytkownika do odpowiedniej strony w zdarzeniu cmdLogin_ServerClick . Przykładowy kod jest dostarczany dla obu scenariuszy. Użyj jednego z nich zgodnie z wymaganiami.

    • Wywołaj metodę , RedirectFromLoginPage aby automatycznie wygenerować plik cookie uwierzytelniania formularzy i przekierować użytkownika do odpowiedniej strony w zdarzeniu cmdLogin_ServerClick :

      private void cmdLogin_ServerClick(object sender, System.EventArgs e)
      {
          if (ValidateUser(txtUserName.Value,txtUserPass.Value))
              FormsAuthentication.RedirectFromLoginPage(txtUserName.Value, chkPersistCookie.Checked);
          else
              Response.Redirect("logon.aspx", true);
      }
      
    • Wygeneruj bilet uwierzytelniania, zaszyfruj go, utwórz plik cookie, dodaj go do odpowiedzi i przekieruj użytkownika. Ta operacja zapewnia większą kontrolę nad sposobem tworzenia pliku cookie. W tym przypadku można również dołączyć dane niestandardowe FormsAuthenticationTicket wraz z elementem .

      private void cmdLogin_ServerClick(object sender, System.EventArgs e)
      {
          if (ValidateUser(txtUserName.Value,txtUserPass.Value))
          {
              FormsAuthenticationTicket tkt;
              string cookiestr;
              HttpCookie ck;
              tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
              DateTime.Now.AddMinutes(30), chkPersistCookie.Checked, "your custom data");
              cookiestr = FormsAuthentication.Encrypt(tkt);
              ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
              if (chkPersistCookie.Checked)
                  ck.Expires=tkt.Expiration;
              ck.Path = FormsAuthentication.FormsCookiePath;
              Response.Cookies.Add(ck);
      
              string strRedirect;
              strRedirect = Request["ReturnUrl"];
              if (strRedirect==null)
                  strRedirect = "default.aspx";
              Response.Redirect(strRedirect, true);
          }
          else
              Response.Redirect("logon.aspx", true);
      }
      
  5. Upewnij się, że następujący kod został dodany do InitializeComponent metody w kodzie, który generuje formularz internetowy Projektant:

    this.cmdLogin.ServerClick += new System.EventHandler(this.cmdLogin_ServerClick);
    

Tworzenie strony Default.aspx

Ta sekcja tworzy stronę testową, do której użytkownicy są przekierowywani po uwierzytelnieniu. Jeśli użytkownicy przeglądają tę stronę bez uprzedniego zalogowania się do aplikacji, nastąpi przekierowanie do strony logowania.

  1. Zmień nazwę istniejącej strony WebForm1.aspx na Default.aspx i otwórz ją w edytorze.

  2. Przełącz się do widoku HTML i skopiuj następujący kod między tagami <form> :

    <input type="submit" Value="SignOut" runat="server" id="cmdSignOut">
    

    Ten przycisk służy do wylogowania się z sesji uwierzytelniania formularzy.

  3. Przejdź do widoku projektu i zapisz stronę.

  4. Zaimportuj wymagane przestrzenie nazw do pliku za kodem:

    using System.Web.Security;
    
  5. Kliknij dwukrotnie pozycję Wyloguj , aby otworzyć stronę z kodem (Default.aspx.cs) i skopiuj następujący kod w procedurze cmdSignOut_ServerClick obsługi zdarzeń:

    private void cmdSignOut_ServerClick(object sender, System.EventArgs e)
    {
        FormsAuthentication.SignOut();
        Response.Redirect("logon.aspx", true);
    }
    
  6. Upewnij się, że następujący kod został dodany do InitializeComponent metody w kodzie, który generuje formularz internetowy Projektant:

    this.cmdSignOut.ServerClick += new System.EventHandler(this.cmdSignOut_ServerClick);
    
  7. Zapisz i skompiluj projekt. Teraz możesz użyć aplikacji.

Dodatkowe uwagi

  • Możesz chcieć bezpiecznie przechowywać hasła w bazie danych. Za pomocą FormsAuthentication funkcji narzędzia klasy o nazwie HashPasswordForStoringInConfigFile można zaszyfrować hasła przed zapisaniem ich w bazie danych lub pliku konfiguracji.

  • Możesz przechowywać informacje o połączeniu SQL w pliku konfiguracji (Web.config), aby można było je łatwo zmodyfikować w razie potrzeby.

  • Możesz rozważyć dodanie kodu, aby uniemożliwić hakerom, którzy próbują używać różnych kombinacji haseł, zalogowanie się. Można na przykład uwzględnić logikę, która akceptuje tylko dwie lub trzy próby logowania. Jeśli użytkownicy nie mogą zalogować się w niektórych próbach, możesz ustawić flagę w bazie danych, aby nie zezwalać im na logowanie, dopóki użytkownicy nie włączą ponownie swoich kont, odwiedzając inną stronę lub wywołując linię pomocy technicznej. Ponadto wszędzie tam, gdzie jest to konieczne, należy dodać odpowiednią obsługę błędów.

  • Ponieważ użytkownik jest identyfikowany na podstawie pliku cookie uwierzytelniania, możesz użyć protokołu Secure Sockets Layer (SSL) w tej aplikacji, aby nikt nie mógł oszukać pliku cookie uwierzytelniania i innych cennych informacji, które są przesyłane.

  • Uwierzytelnianie oparte na formularzach wymaga, aby klient akceptował lub włączał pliki cookie w przeglądarce.

  • Parametr limitu <authentication> czasu sekcji konfiguracji kontroluje interwał ponownego generowania pliku cookie uwierzytelniania. Możesz wybrać wartość, która zapewnia lepszą wydajność i bezpieczeństwo.

  • Niektóre pośrednie serwery proxy i pamięci podręczne w Internecie mogą buforować odpowiedzi serwera sieci Web zawierające Set-Cookie nagłówki, które są następnie zwracane do innego użytkownika. Ponieważ uwierzytelnianie oparte na formularzach używa pliku cookie do uwierzytelniania użytkowników, takie zachowanie może spowodować przypadkowe (lub celowe) personifikowanie innego użytkownika przez odebranie pliku cookie z pośredniczącego serwera proxy lub pamięci podręcznej, które nie były pierwotnie dla nich przeznaczone.

Informacje