Implementar a autenticação baseada em formulários em um aplicativo ASP.NET usando C#.NET

Este artigo demonstra como implementar a autenticação baseada em formulários usando um banco de dados para armazenar os usuários. Ele se refere aos seguintes namespaces da Biblioteca de Classes do Microsoft .NET Framework:

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

Versão original do produto: ASP.NET
Número original do KB: 301240

Requisitos

A lista a seguir descreve os pacotes de serviço, software, infraestrutura de rede e hardware recomendados que você precisa:

  • Visual Studio .NET
  • IIS (Serviços de Informações da Internet) versão 5.0 ou posterior
  • SQL Server

Criar um aplicativo ASP.NET usando o .NET do C#

  1. Abra o Visual Studio .NET.
  2. Crie um novo aplicativo Web ASP.NET e especifique o nome e o local.

Configurar configurações de segurança no Arquivo Web.config

Esta seção demonstra como adicionar e modificar as <authentication> seções e <authorization> configuração para configurar o aplicativo ASP.NET para usar a autenticação baseada em formulários.

  1. No Gerenciador de Soluções, abra o arquivo Web.config.

  2. Altere o modo de autenticação para Forms.

  3. Insira a <Forms> marca e preencha os atributos apropriados. Copie o código a seguir e selecione Colar como HTML no menu Editar para colar o código na <authentication> seção do arquivo:

    <authentication mode="Forms">
        <forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx"
            protection="All" path="/" timeout="30" />
    </authentication>
    
  4. Negar acesso ao usuário anônimo na seção da <authorization> seguinte maneira:

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

Criar uma tabela de banco de dados de exemplo para armazenar detalhes dos usuários

Esta seção mostra como criar um banco de dados de exemplo para armazenar o nome de usuário, a senha e a função para os usuários. Você precisa da coluna de função se quiser armazenar funções de usuário no banco de dados e implementar a segurança baseada em função.

  1. No menu Iniciar , selecione Executar e digite bloco de notas para abrir o Bloco de Notas.

  2. Realce o código de script SQL a seguir, clique com o botão direito do mouse no código e selecione Copiar. No Bloco de Notas, selecione Colar no menu Editar para colar o seguinte código:

    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. Salve o arquivo como Users.sql.

  4. No computador SQL Server, abra Users.sql no Analisador de Consultas. Na lista de bancos de dados, selecione pubs e execute o script. Essa operação cria uma tabela de usuários de exemplo e preenche a tabela no banco de dados Pubs a ser usada com este aplicativo de exemplo.

Criar uma página Logon.aspx

  1. Adicione um novo Formulário Web ao projeto chamado Logon.aspx.

  2. Abra a página Logon.aspx no editor e alterne para a exibição HTML.

  3. Copie o código a seguir e use a opção Colar como HTML no menu Editar para inserir o código entre as <form> marcas:

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

    Esse Formulário Web é usado para apresentar um formulário de logon aos usuários para que eles possam fornecer seu nome de usuário e senha para fazer logon no aplicativo.

  4. Alterne para a exibição Design e salve a página.

Codificar o manipulador de eventos para que ele valide as credenciais do usuário

Esta seção apresenta o código colocado na página code-behind (Logon.aspx.cs).

  1. Clique duas vezes em Logon para abrir o arquivo Logon.aspx.cs .

  2. Importe os namespaces necessários no arquivo code-behind:

    using System.Data.SqlClient;
    using System.Web.Security;
    
  3. Crie uma ValidateUser função para validar as credenciais do usuário procurando no banco de dados. Verifique se você altera a Connection cadeia de caracteres para apontar para o banco de dados.

    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. Você pode usar um dos dois métodos para gerar o cookie de autenticação de formulários e redirecionar o usuário para uma página apropriada no cmdLogin_ServerClick evento. O código de exemplo é fornecido para ambos os cenários. Use um deles de acordo com suas necessidades.

    • Chame o RedirectFromLoginPage método para gerar automaticamente o cookie de autenticação de formulários e redirecionar o usuário para uma página apropriada no cmdLogin_ServerClick evento:

      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);
      }
      
    • Gere o tíquete de autenticação, criptografe-o, crie um cookie, adicione-o à resposta e redirecione o usuário. Essa operação oferece mais controle sobre como você cria o cookie. Você também pode incluir dados personalizados junto com o FormsAuthenticationTicket nesse caso.

      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. Verifique se o código a seguir é adicionado ao InitializeComponent método no código que o Formulário Web Designer gera:

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

Criar uma página Default.aspx

Esta seção cria uma página de teste para a qual os usuários são redirecionados após a autenticação. Se os usuários navegarem até esta página sem primeiro fazer logon no aplicativo, eles são redirecionados para a página de logon.

  1. Renomeie a página WebForm1.aspx existente como Default.aspx e abra-a no editor.

  2. Alterne para a exibição HTML e copie o seguinte código entre as <form> marcas:

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

    Esse botão é usado para fazer logon da sessão de autenticação de formulários.

  3. Alterne para a exibição Design e salve a página.

  4. Importe os namespaces necessários no arquivo code-behind:

    using System.Web.Security;
    
  5. Clique duas vezes em SignOut para abrir a página de código atrás (Default.aspx.cs) e copie o seguinte código no cmdSignOut_ServerClick manipulador de eventos:

    private void cmdSignOut_ServerClick(object sender, System.EventArgs e)
    {
        FormsAuthentication.SignOut();
        Response.Redirect("logon.aspx", true);
    }
    
  6. Verifique se o código a seguir é adicionado ao InitializeComponent método no código que o Formulário Web Designer gera:

    this.cmdSignOut.ServerClick += new System.EventHandler(this.cmdSignOut_ServerClick);
    
  7. Salve e compile o projeto. Agora você pode usar o aplicativo.

Observações adicionais

  • Talvez você queira armazenar senhas com segurança em um banco de dados. Você pode usar a função de utilitário de FormsAuthentication classe nomeada HashPasswordForStoringInConfigFile para criptografar as senhas antes de armazená-las no banco de dados ou no arquivo de configuração.

  • Talvez você queira armazenar as informações de conexão SQL no arquivo de configuração (Web.config) para que você possa modificá-las facilmente, se necessário.

  • Você pode considerar adicionar código para impedir que hackers que tentam usar diferentes combinações de senhas faça logon. Por exemplo, você pode incluir a lógica que aceita apenas duas ou três tentativas de logon. Se os usuários não puderem fazer logon em algumas tentativas, talvez você queira definir um sinalizador no banco de dados para não permitir que eles façam logon até que os usuários habilitem novamente suas contas visitando uma página diferente ou chamando sua linha de suporte. Além disso, você deve adicionar o tratamento de erro apropriado sempre que necessário.

  • Como o usuário é identificado com base no cookie de autenticação, talvez você queira usar a SSL (Secure Sockets Layer) neste aplicativo para que ninguém possa enganar o cookie de autenticação e quaisquer outras informações valiosas que estão sendo transmitidas.

  • A autenticação baseada em formulários exige que seu cliente aceite ou habilite cookies no navegador.

  • O parâmetro de tempo limite da <authentication> seção de configuração controla o intervalo em que o cookie de autenticação é regenerado. Você pode escolher um valor que forneça melhor desempenho e segurança.

  • Determinados proxies e caches intermediários na Internet podem armazenar em cache respostas de servidor Web que contêm Set-Cookie cabeçalhos, que são então retornados a um usuário diferente. Como a autenticação baseada em formulários usa um cookie para autenticar usuários, esse comportamento pode fazer com que os usuários se representem acidentalmente (ou intencionalmente) por outro usuário recebendo um cookie de um proxy ou cache intermediário que não foi originalmente destinado a eles.

Referências