Implementare l'autenticazione basata su form in un'applicazione ASP.NET usando C#.NET

Questo articolo illustra come implementare l'autenticazione basata su moduli usando un database per archiviare gli utenti. Fa riferimento agli spazi dei nomi della libreria di classi di Microsoft .NET Framework seguenti:

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

Versione originale del prodotto: ASP.NET
Numero KB originale: 301240

Requisiti

L'elenco seguente descrive l'hardware, il software, l'infrastruttura di rete e i Service Pack consigliati necessari:

  • Visual Studio .NET
  • Internet Information Services (IIS) versione 5.0 o successiva
  • SQL Server

Creare un'applicazione ASP.NET usando C# .NET

  1. Aprire Visual Studio .NET.
  2. Creare una nuova applicazione Web ASP.NET e specificare il nome e il percorso.

Configurare le impostazioni di sicurezza nel file Web.config

Questa sezione illustra come aggiungere e modificare le <authentication> sezioni di configurazione e <authorization> per configurare l'applicazione ASP.NET per l'uso dell'autenticazione basata su moduli.

  1. In Esplora soluzioni aprire il file Web.config.

  2. Modificare la modalità di autenticazione in Moduli.

  3. Inserire il <Forms> tag e riempire gli attributi appropriati. Copiare il codice seguente e quindi selezionare Incolla come HTML dal menu Modifica per incollare il codice nella <authentication> sezione del file:

    <authentication mode="Forms">
        <forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx"
            protection="All" path="/" timeout="30" />
    </authentication>
    
  4. Negare l'accesso all'utente anonimo nella <authorization> sezione come indicato di seguito:

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

Creare una tabella di database di esempio per archiviare i dettagli degli utenti

Questa sezione illustra come creare un database di esempio per archiviare il nome utente, la password e il ruolo per gli utenti. È necessaria la colonna del ruolo se si desidera archiviare i ruoli utente nel database e implementare la sicurezza basata sui ruoli.

  1. Nel menu Start selezionare Esegui e quindi digitare blocco note per aprire il Blocco note.

  2. Evidenziare il codice script SQL seguente, fare clic con il pulsante destro del mouse sul codice e quindi scegliere Copia. Nel Blocco note selezionare Incolla dal menu Modifica per incollare il codice seguente:

    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. Salvare il file come Users.sql.

  4. Nel computer SQL Server aprire Users.sql in Analizzatore query. Nell'elenco dei database selezionare pubs ed eseguire lo script. Questa operazione crea una tabella degli utenti di esempio e popola la tabella nel database Pubs da usare con questa applicazione di esempio.

Creare una pagina di Logon.aspx

  1. Aggiungere un nuovo Web Form al progetto denominato Logon.aspx.

  2. Aprire la pagina Logon.aspx nell'editor e passare alla visualizzazione HTML.

  3. Copiare il codice seguente e usare l'opzione Incolla come HTML nel menu Modifica per inserire il codice tra i <form> tag:

    <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" />
    

    Questo Modulo Web viene usato per presentare un modulo di accesso agli utenti in modo che possano specificare il nome utente e la password per accedere all'applicazione.

  4. Passare alla visualizzazione Progettazione e salvare la pagina.

Codificare il gestore eventi in modo che convalidi le credenziali utente

Questa sezione presenta il codice inserito nella pagina code-behind (Logon.aspx.cs).

  1. Fare doppio clic su Accesso per aprire il file Logon.aspx.cs .

  2. Importare gli spazi dei nomi necessari nel file code-behind:

    using System.Data.SqlClient;
    using System.Web.Security;
    
  3. Creare una ValidateUser funzione per convalidare le credenziali utente cercando nel database. Assicurarsi di modificare la Connection stringa in modo che punti al database.

    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. È possibile usare uno dei due metodi per generare il cookie di autenticazione basata su form e reindirizzare l'utente a una pagina appropriata nell'evento cmdLogin_ServerClick . Il codice di esempio viene fornito per entrambi gli scenari. Usare uno di essi in base alle proprie esigenze.

    • Chiamare il RedirectFromLoginPage metodo per generare automaticamente il cookie di autenticazione basata su form e reindirizzare l'utente a una pagina appropriata nell'evento 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);
      }
      
    • Generare il ticket di autenticazione, crittografarlo, creare un cookie, aggiungerlo alla risposta e reindirizzare l'utente. Questa operazione offre un maggiore controllo sulla modalità di creazione del cookie. In questo caso è anche possibile includere dati personalizzati insieme a FormsAuthenticationTicket .

      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. Assicurarsi che il codice seguente venga aggiunto al InitializeComponent metodo nel codice generato dal Designer Web Form:

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

Creare una pagina di Default.aspx

Questa sezione crea una pagina di test a cui gli utenti vengono reindirizzati dopo l'autenticazione. Se gli utenti accedono a questa pagina senza prima accedere all'applicazione, vengono reindirizzati alla pagina di accesso.

  1. Rinominare la pagina WebForm1.aspx esistente come Default.aspx e aprirla nell'editor.

  2. Passare alla visualizzazione HTML e copiare il codice seguente tra i <form> tag:

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

    Questo pulsante viene usato per disconnettersi dalla sessione di autenticazione basata su form.

  3. Passare alla visualizzazione Progettazione e salvare la pagina.

  4. Importare gli spazi dei nomi necessari nel file code-behind:

    using System.Web.Security;
    
  5. Fare doppio clic su SignOut per aprire la pagina code-behind (Default.aspx.cs) e copiare il codice seguente nel cmdSignOut_ServerClick gestore eventi:

    private void cmdSignOut_ServerClick(object sender, System.EventArgs e)
    {
        FormsAuthentication.SignOut();
        Response.Redirect("logon.aspx", true);
    }
    
  6. Assicurarsi che il codice seguente venga aggiunto al InitializeComponent metodo nel codice generato dal Designer Web Form:

    this.cmdSignOut.ServerClick += new System.EventHandler(this.cmdSignOut_ServerClick);
    
  7. Salvare e compilare il progetto. È ora possibile usare l'applicazione.

Note aggiuntive

  • È possibile archiviare le password in modo sicuro in un database. È possibile usare la FormsAuthentication funzione di utilità di classe denominata HashPasswordForStoringInConfigFile per crittografare le password prima di archiviarle nel database o nel file di configurazione.

  • È possibile archiviare le informazioni di connessione SQL nel file di configurazione (Web.config) in modo che sia possibile modificarle facilmente, se necessario.

  • È possibile prendere in considerazione l'aggiunta di codice per impedire agli hacker che tentano di usare diverse combinazioni di password di accedere. Ad esempio, è possibile includere la logica che accetta solo due o tre tentativi di accesso. Se gli utenti non possono accedere in alcuni tentativi, è possibile impostare un flag nel database per non consentire loro di accedere fino a quando gli utenti non riabilitare i propri account visitando una pagina diversa o chiamando la riga di supporto. Inoltre, è consigliabile aggiungere la gestione degli errori appropriata quando necessario.

  • Poiché l'utente viene identificato in base al cookie di autenticazione, è possibile usare Secure Sockets Layer (SSL) su questa applicazione in modo che nessuno possa ingannare il cookie di autenticazione e qualsiasi altra informazione preziosa che viene trasmessa.

  • L'autenticazione basata su moduli richiede che il client accetti o abiliti i cookie nel browser.

  • Il parametro timeout della <authentication> sezione di configurazione controlla l'intervallo di rigenerazione del cookie di autenticazione. È possibile scegliere un valore che offre prestazioni e sicurezza migliori.

  • Alcuni proxy intermedi e cache su Internet possono memorizzare nella cache le risposte del server Web contenenti Set-Cookie intestazioni, che vengono quindi restituite a un altro utente. Poiché l'autenticazione basata su moduli usa un cookie per autenticare gli utenti, questo comportamento può causare la rappresentazione accidentale (o intenzionale) di un altro utente da parte degli utenti tramite la ricezione di un cookie da un proxy intermediario o da una cache che in origine non era destinata a loro.

Riferimenti