Implementación de la autenticación basada en formularios en una aplicación de ASP.NET mediante C#.NET

En este artículo se muestra cómo implementar la autenticación basada en formularios mediante una base de datos para almacenar a los usuarios. Hace referencia a los siguientes espacios de nombres de la biblioteca de clases de Microsoft .NET Framework:

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

              Versión original del producto: ASP.NET
Número de KB original: 301240

Requisitos

En la lista siguiente se describen el hardware, el software, la infraestructura de red y los Service Pack recomendados que necesita:

  • Visual Studio .NET
  • Internet Information Services (IIS) versión 5.0 o posterior
  • SQL Server

Creación de una aplicación ASP.NET mediante .NET de C#

  1. Abra Visual Studio .NET.
  2. Cree una nueva aplicación web ASP.NET y especifique el nombre y la ubicación.

Configuración de las opciones de seguridad en el archivo Web.config

En esta sección se muestra cómo agregar y modificar las <authentication> secciones y <authorization> de configuración para configurar la aplicación ASP.NET para usar la autenticación basada en formularios.

  1. En el Explorador de soluciones, abra el archivo Web.config.

  2. Cambie el modo de autenticación a Formularios.

  3. Inserte la <Forms> etiqueta y rellene los atributos adecuados. Copie el código siguiente y, a continuación, seleccione Pegar como HTML en el menú Editar para pegar el código en la <authentication> sección del archivo:

    <authentication mode="Forms">
        <forms name=".ASPXFORMSDEMO" loginUrl="logon.aspx"
            protection="All" path="/" timeout="30" />
    </authentication>
    
  4. Deniegue el acceso al usuario anónimo en la sección de la <authorization> siguiente manera:

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

Creación de una tabla de base de datos de ejemplo para almacenar los detalles de los usuarios

En esta sección se muestra cómo crear una base de datos de ejemplo para almacenar el nombre de usuario, la contraseña y el rol de los usuarios. Necesita la columna de rol si desea almacenar roles de usuario en la base de datos e implementar la seguridad basada en roles.

  1. En el menú Inicio , seleccione Ejecutar y escriba bloc de notas para abrir el Bloc de notas.

  2. Resalte el siguiente código de script SQL, haga clic con el botón derecho en el código y seleccione Copiar. En el Bloc de notas, seleccione Pegar en el menú Editar para pegar el código siguiente:

    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. Guarde el archivo como Users.sql.

  4. En el equipo SQL Server, abra Users.sql en el Analizador de consultas. En la lista de bases de datos, seleccione pubs y ejecute el script. Esta operación crea una tabla de usuarios de ejemplo y rellena la tabla de la base de datos Pubs que se va a usar con esta aplicación de ejemplo.

Crear una página de Logon.aspx

  1. Agregue un nuevo formulario web al proyecto denominado Logon.aspx.

  2. Abra la página Logon.aspx en el editor y cambie a la vista HTML.

  3. Copie el código siguiente y use la opción Pegar como HTML en el menú Editar para insertar el código entre las <form> etiquetas:

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

    Este formulario web se usa para presentar un formulario de inicio de sesión a los usuarios para que puedan proporcionar su nombre de usuario y contraseña para iniciar sesión en la aplicación.

  4. Cambie a la vista Diseño y guarde la página.

Codificar el controlador de eventos para que valide las credenciales de usuario

En esta sección se presenta el código que se coloca en la página de código subyacente (Logon.aspx.cs).

  1. Haga doble clic en Inicio de sesión para abrir el archivo Logon.aspx.cs .

  2. Importe los espacios de nombres necesarios en el archivo de código subyacente:

    using System.Data.SqlClient;
    using System.Web.Security;
    
  3. Cree una ValidateUser función para validar las credenciales de usuario buscando en la base de datos. Asegúrese de cambiar la Connection cadena para que apunte a la base de datos.

    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. Puede usar uno de los dos métodos para generar la cookie de autenticación de formularios y redirigir al usuario a una página adecuada en el cmdLogin_ServerClick evento. Se proporciona código de ejemplo para ambos escenarios. Use cualquiera de ellos según sus necesidades.

    • Llame al RedirectFromLoginPage método para generar automáticamente la cookie de autenticación de formularios y redirigir al usuario a una página adecuada en el 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);
      }
      
    • Genere el vale de autenticación, cifre, cree una cookie, agréguela a la respuesta y redirija al usuario. Esta operación le proporciona más control sobre cómo crear la cookie. También puede incluir datos personalizados junto con en FormsAuthenticationTicket este 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. Asegúrese de que el código siguiente se agrega al InitializeComponent método en el código que el formulario web Designer genera:

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

Crear una página de Default.aspx

En esta sección se crea una página de prueba a la que se redirige a los usuarios después de autenticarse. Si los usuarios van a esta página sin iniciar sesión primero en la aplicación, se les redirigirá a la página de inicio de sesión.

  1. Cambie el nombre de la página de WebForm1.aspx existente como Default.aspx y ábrala en el editor.

  2. Cambie a la vista HTML y copie el código siguiente entre las <form> etiquetas:

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

    Este botón se usa para cerrar la sesión de autenticación de formularios.

  3. Cambie a la vista Diseño y guarde la página.

  4. Importe los espacios de nombres necesarios en el archivo de código subyacente:

    using System.Web.Security;
    
  5. Haga doble clic en Cerrar sesión para abrir la página de código subyacente (Default.aspx.cs) y copie el código siguiente en el controlador de cmdSignOut_ServerClick eventos:

    private void cmdSignOut_ServerClick(object sender, System.EventArgs e)
    {
        FormsAuthentication.SignOut();
        Response.Redirect("logon.aspx", true);
    }
    
  6. Asegúrese de que el código siguiente se agrega al InitializeComponent método en el código que el formulario web Designer genera:

    this.cmdSignOut.ServerClick += new System.EventHandler(this.cmdSignOut_ServerClick);
    
  7. Guarde y compile el proyecto. Ahora puede usar la aplicación.

Notas adicionales

  • Es posible que desee almacenar contraseñas de forma segura en una base de datos. Puede usar la FormsAuthentication función de utilidad de clase denominada HashPasswordForStoringInConfigFile para cifrar las contraseñas antes de almacenarlas en la base de datos o el archivo de configuración.

  • Es posible que desee almacenar la información de conexión SQL en el archivo de configuración (Web.config) para que pueda modificarla fácilmente si es necesario.

  • Puede considerar la posibilidad de agregar código para evitar que los hackers que intentan usar diferentes combinaciones de contraseñas inicien sesión. Por ejemplo, puede incluir lógica que acepte solo dos o tres intentos de inicio de sesión. Si los usuarios no pueden iniciar sesión en algunos intentos, es posible que quiera establecer una marca en la base de datos para que no les permita iniciar sesión hasta que los usuarios vuelvan a habilitar sus cuentas visitando una página diferente o llamando a la línea de soporte técnico. Además, debe agregar el control de errores adecuado siempre que sea necesario.

  • Dado que el usuario se identifica en función de la cookie de autenticación, es posible que desee usar capa de sockets seguros (SSL) en esta aplicación para que nadie pueda engañar a la cookie de autenticación y a cualquier otra información valiosa que se esté transmitiendo.

  • La autenticación basada en formularios requiere que el cliente acepte o habilite cookies en su explorador.

  • El parámetro timeout de la <authentication> sección de configuración controla el intervalo en el que se vuelve a generar la cookie de autenticación. Puede elegir un valor que proporcione un mejor rendimiento y seguridad.

  • Algunos servidores proxy intermedios y cachés en Internet pueden almacenar en caché las respuestas del servidor web que contienen Set-Cookie encabezados, que luego se devuelven a un usuario diferente. Dado que la autenticación basada en formularios usa una cookie para autenticar a los usuarios, este comportamiento puede hacer que los usuarios suplante accidentalmente (o intencionadamente) a otro usuario mediante la recepción de una cookie de un proxy o caché intermediarios que no estaba diseñado originalmente para ellos.

Referencias