Exportar (0) Imprimir
Expandir todo

Cómo: Utilizar la autenticación mediante Formularios con SQL Server 2000

Publicado: 26 de junio de 2006

Consulte la Página de entrada como punto de partida y para obtener una descripción completa del documento Crear aplicaciones ASP.NET seguras.

Resumen: En este artículo se muestra cómo implementar la autenticación mediante Formularios con un almacén de credenciales de SQL Server. También se describe cómo almacenar compendios de contraseñas en la base de datos.

Las aplicaciones Web que utilizan la autenticación mediante Formularios suelen almacenar las credenciales de los usuarios (nombre de usuario y contraseña) junto con listas de funciones o grupos asociadas en Microsoft® SQL Server™ 2000.
En este artículo se describe cómo consultar nombres de usuario y validar contraseñas de forma segura en SQL Server 2000. En relación con el almacenamiento seguro de credenciales de usuario hay dos conceptos clave:

Almacenar compendios de contraseñas. Por razones de seguridad, las contraseñas no se deben almacenar en texto sin cifrar en la base de datos. En este artículo se describe cómo crear y almacenar un valor hash unidireccional de la contraseña de un usuario en lugar de la contraseña propiamente dicha. Se prefiere este método a almacenar una versión cifrada de la contraseña del usuario, ya que así se evitan los problemas de administración de claves asociados a las técnicas de cifrado.

Para mayor seguridad y para mitigar la amenaza relativa a los ataques de diccionario, en el método que se describe en este artículo se combina un valor salt (número aleatorio generado mediante criptografía) con la contraseña, antes de crear el valor hash de contraseña.

Importante: la desventaja de no almacenar las contraseñas en la base de datos es que si un usuario olvida su contraseña, ésta no se puede recuperar. En consecuencia, la aplicación debe utilizar sugerencias de contraseña y almacenarlas junto con el compendio de contraseñas en la base de datos.

Validar los datos suministrados por el usuario. Si se pasan a los comandos de SQL datos suministrados por el usuario, por ejemplo como literales de cadena en instrucciones de comparación o de coincidencia de patrones, debe ponerse mucho cuidado en la validación de los datos para asegurar que los comandos resultantes no contienen errores de sintaxis y que ningún intruso puede hacer que la aplicación ejecute comandos SQL arbitrarios. La validación del nombre de usuario suministrado durante un proceso de inicio de sesión es fundamental, ya que el modelo de seguridad de la aplicación depende completamente de su capacidad para autenticar a los usuarios de forma correcta y segura.

Para obtener más información acerca de cómo validar datos suministrados por los usuarios para los comandos SQL y para funciones de validación, consulte "Ataques de inyección SQL" en el capítulo 12, "Seguridad del acceso a datos".

Requisitos
A continuación se describen las recomendaciones de hardware, software, infraestructura de red, conocimientos y Service Pack que se necesitan.
Sistema operativo Microsoft Windows® 2000
Sistema de desarrollo Microsoft Visual Studio® .NET
Microsoft SQL Server 2000

En esta página

Crear una aplicación Web con una página de inicio de sesión  Crear una aplicación Web con una página de inicio de sesión
Configurar la aplicación Web para la autenticación mediante Formularios Configurar la aplicación Web para la autenticación mediante Formularios
Desarrollar funciones para generar un valor hash y un valor salt  Desarrollar funciones para generar un valor hash y un valor salt
Crear una base de datos de cuentas de usuario Crear una base de datos de cuentas de usuario
Utilizar ADO.NET para almacenar detalles de cuentas en la base de datos Utilizar ADO.NET para almacenar detalles de cuentas en la base de datos
Autenticar credenciales de usuario con la base de datos Autenticar credenciales de usuario con la base de datos
Probar la aplicación Probar la aplicación
Recursos adicionales Recursos adicionales

Crear una aplicación Web con una página de inicio de sesión

En este procedimiento se crea una sencilla aplicación Web en C#, la cual contiene una página de inicio de sesión que permite a los usuarios escribir un nombre de usuario y una contraseña.

Para crear una aplicación Web con una página de inicio de sesión

  • Inicie Visual Studio .NET y cree una nueva aplicación Web ASP.NET en C# con el nombre FormsAuthSQL.

  • Utilice el Explorador de soluciones para cambiar el nombre de WebForm1.aspx por Logon.aspx.

  • Agregue a Logon.aspx los controles que se enumeran en la tabla 1 para crear un sencillo formulario de inicio de sesión.

    Tabla 1: Controles de Logon.aspx

    Tipo de control

    Texto

    Id.

    Etiqueta

    User Name:

    -

    Etiqueta

    Password:

    -

    Cuadro de texto

    -

    txtUserName

    Cuadro de texto

    -

    txtPassword

    Botón

    Register

    btnRegister

    Botón

    Logon

    btnLogon

    Etiqueta

    -

    lblMessage

    La página Web debe ser similar a la que se muestra en la ilustración 1.

    imagen

    {Insert figure: How To - LogonWebForm.gif}
    Ilustración 1
    Formulario Web de página de inicio de sesión

  • Establezca el valor Password en la propiedad TextMode de txtPassword.

Configurar la aplicación Web para la autenticación mediante Formularios

En este procedimiento se modifica el archivo Web.config de la aplicación para configurarla de forma que admita la autenticación mediante Formularios.

Para configurar la aplicación Web para la autenticación mediante Formularios

  1. Utilice el Explorador de soluciones para abrir Web.config.

  2. Busque el elemento <authentication> y cambie el atributo mode a Forms.

  3. Agregue el elemento <forms> siguiente como elemento secundario del elemento <authentication> y establezca los atributos loginUrl, name, timeout y path como se muestra a continuación.

    <authentication mode="Forms">
       <forms loginUrl="logon.aspx" name="sqlAuthCookie" timeout="60"    path="/">
       </forms>
       </authentication>
    
  4. Agregue el siguiente elemento <authorization> debajo del elemento <authentication>. Esto permitirá que sólo los usuarios autenticados tengan acceso a la aplicación. El atributo loginUrl del elemento <authentication> establecido anteriormente redirigirá las solicitudes no autenticadas a la página logon.aspx.

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

Desarrollar funciones para generar un valor hash y un valor salt

En este procedimiento se agregan dos métodos de utilidades a la aplicación Web: uno para generar un valor salt aleatorio y otro para crear un valor hash basado en una contraseña suministrada y un valor salt.

Para desarrollar funciones para generar un valor hash y un valor salt

  1. Abra Logon.aspx.cs y agregue las siguientes instrucciones using al principio del archivo debajo de las instrucciones using existentes.

    using System.Security.Cryptography;
       using System.Web.Security;
    
  2. Agregue el siguiente método estático a la clase WebForm1 para generar un valor salt aleatorio y devolverlo como una cadena codificada en Base 64.

    private static string CreateSalt(int size)
       {
       // Generate a cryptographic random number using the cryptographic
       // service provider
       RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
       byte[] buff = new byte[size];
       rng.GetBytes(buff);
       // Return a Base64 string representation of the random number
       return Convert.ToBase64String(buff);
       }
    
  3. Agregue el siguiente método estático para generar un valor hash basado en una contraseña suministrada y un valor salt.

    private static string CreatePasswordHash(string pwd, string salt)
       {
       string saltAndPwd = String.Concat(pwd, salt);
       string hashedPwd = 
       FormsAuthentication.HashPasswordForStoringInConfigFile(
       saltAndPwd, "SHA1");
       return hashedPwd;
       }
    

Crear una base de datos de cuentas de usuario

En este procedimiento se crea una nueva base de datos de cuentas de usuario en SQL Server que contiene una única tabla de usuarios y un procedimiento almacenado que se utiliza para consultar la base de datos de usuarios.

Para crear una base de datos de cuentas de usuario

  1. En el menú de programas de Microsoft SQL Server, haga clic en Analizador de consultas y, después, conecte al servidor SQL Server local.

  2. Escriba la siguiente secuencia de comandos de SQL. Observe que debe reemplazar "LocalMachine" por el nombre de su equipo al final de la secuencia de comandos.

    USE master
       GO
       -- create a database for the security information
       IF EXISTS (SELECT * FROM master..sysdatabases WHERE name = 'UserAccounts')
       DROP DATABASE UserAccounts
       GO
       CREATE DATABASE UserAccounts
       GO
       USE UserAccounts
       GO
       CREATE TABLE [Users] (
       [UserName] [varchar] (255) NOT NULL ,
       [PasswordHash] [varchar] (40) NOT NULL ,
       [salt] [varchar] (10) NOT NULL,
       CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
       (
       [UserName]
       ) ON [PRIMARY] 
       ) ON [PRIMARY]
       GO
       -- create stored procedure to register user details
       CREATE PROCEDURE RegisterUser
       @userName varchar(255),
       @passwordHash varchar(40),
       @salt varchar(10)
       AS
       INSERT INTO Users VALUES(@userName, @passwordHash, @salt)
       GO
       -- create stored procedure to retrieve user details
       CREATE PROCEDURE LookupUser
       @userName varchar(255)
       AS
       SELECT PasswordHash, salt 
       FROM Users
       WHERE UserName = @userName
       GO
       -- Add a login for the local ASPNET account
       -- In the following statements, replace LocalMachine with your 
       -- local machine name
       exec sp_grantlogin [LocalMachine\ASPNET]
       -- Add a database login for the UserAccounts database for the ASPNET account
       exec sp_grantdbaccess [LocalMachine\ASPNET]
       -- Grant execute permissions to the LookupUser and RegisterUser stored procs
       grant execute on LookupUser to [LocalMachine\ASPNET]
       grant execute on RegisterUser to [LocalMachine\ASPNET]
    
  3. Ejecute la consulta para crear la base de datos UserAccounts.

  4. Salga del Administrador de consultas.

Utilizar ADO.NET para almacenar detalles de cuentas en la base de datos

En este procedimiento se modifica el código de la aplicación Web para almacenar el nombre de usuario suministrado, el valor hash de la contraseña generado y el valor salt en la base de datos.

Para utilizar ADO.NET para almacenar detalles de cuentas en la base de datos

  1. Vuelva a Visual Studio .NET y haga doble clic en el botón Register del formulario Web para crear un controlador de eventos para gestionar eventos de clic sobre este botón.

  2. Agregue al método el siguiente código.

    string salt = CreateSalt(5);
       string passwordHash = CreatePasswordHash(txtPassword.Text,salt);
       try
       {
       StoreAccountDetails( txtUserName.Text, passwordHash, salt);
       }
       catch (Exception ex)
       {
       lblMessage.Text = ex.Message;
       }
    
  3. Al principio del archivo, agregue la siguiente instrucción using debajo de las instrucciones using existentes.

    using System.Data.SqlClient;
    
  4. Agregue el método de utilidad StoreAccountDetails con el siguiente código. En este código se utiliza ADO.NET para conectar a la base de datos UserAccounts y se almacenan en la tabla Users el nombre de usuario suministrado, el valor hash de contraseña y el valor salt.

    private void StoreAccountDetails( string userName, 
       string passwordHash, 
       string salt )
       {
       // See "How To Use DPAPI (Machine Store) from ASP.NET" for information    
       // about securely storing connection strings.
       SqlConnection conn = new SqlConnection( "Server=(local);" +
       "Integrated Security=SSPI;" +
       "database=UserAccounts");
    
    SqlCommand cmd = new SqlCommand("RegisterUser", conn );
       cmd.CommandType = CommandType.StoredProcedure;
       SqlParameter sqlParam = null;
    
    sqlParam = cmd.Parameters.Add("@userName", SqlDbType.VarChar, 255);
       sqlParam.Value = userName;
    
    sqlParam = cmd.Parameters.Add("@passwordHash ", SqlDbType.VarChar,    40);
       sqlParam.Value = passwordHash;
    
    sqlParam = cmd.Parameters.Add("@salt", SqlDbType.VarChar, 10);
       sqlParam.Value = salt;
    
    try
       {
       conn.Open();
       cmd.ExecuteNonQuery();
       }
       catch (Exception ex)
       {
       // Code to check for primary key violation (duplicate account name)
       // or other database errors omitted for clarity
       throw new Exception("Exception adding account. " + ex.Message);
       }
       finally
       {
       conn.Close();
       } 
       }
    

Autenticar credenciales de usuario con la base de datos

En este procedimiento se desarrolla código de ADO.NET para consultar en la base de datos el nombre de usuario suministrado y validar la contraseña suministrada mediante valores hash de contraseña coincidentes.

Nota

en muchos casos de autenticación mediante Formularios en los que se utiliza autorización basada en funciones de .NET, en este punto también se pueden recuperar en la base de datos las funciones a las que pertenece el usuario. Posteriormente se pueden utilizar para generar un objeto GenericPrincipal que se puede asociar con las solicitudes Web autenticadas, a efectos de autorización en .NET.
Para obtener más información acerca de cómo construir un vale de autenticación mediante Formularios que incorpore los detalles de función de un usuario, consulte "Cómo: Utilizar la autenticación mediante Formularios con objetos GenericPrincipal" en la sección Referencia de esta guía.

Para autenticar credenciales de usuario con la base de datos

  1. Vuelva al archivo Logon.aspx.cs y agregue el método auxiliar privado VerifyPassword como se indica en el código siguiente.

    private bool VerifyPassword(string suppliedUserName, 
       string suppliedPassword )
       { 
       bool passwordMatch = false;
       // Get the salt and pwd from the database based on the user name.
       // See "How To: Use DPAPI (Machine Store) from ASP.NET," "How    To: Use DPAPI 
       // (User Store) from Enterprise Services," and "How To: Create a DPAPI    
       // Library" for more information about how to use DPAPI to securely store    
       // connection strings.
       SqlConnection conn = new SqlConnection( "Server=(local);" +
       "Integrated Security=SSPI;" +
       "database=UserAccounts");
       SqlCommand cmd = new SqlCommand( "LookupUser", conn );
       cmd.CommandType = CommandType.StoredProcedure;
    
    SqlParameter sqlParam = cmd.Parameters.Add("@userName", 
       SqlDbType.VarChar, 255);
       sqlParam.Value = suppliedUserName;
       try
       {
       conn.Open();
       SqlDataReader reader = cmd.ExecuteReader();
       reader.Read(); // Advance to the one and only row
       // Return output parameters from returned data stream
       string dbPasswordHash = reader.GetString(0);
       string salt = reader.GetString(1);
       reader.Close();
       // Now take the salt and the password entered by the user
       // and concatenate them together.
       string passwordAndSalt = String.Concat(suppliedPassword, salt);
       // Now hash them
       string hashedPasswordAndSalt = 
       FormsAuthentication.HashPasswordForStoringInConfigFile(
       passwordAndSalt, "SHA1");
       // Now verify them.
       passwordMatch = hashedPasswordAndSalt.Equals(dbPasswordHash);
       }
       catch(Exception ex)
       {
       throw new Exception("Execption verifying password. " + ex.Message);
       }
       finally
       {
       conn.Close();
       }
       return passwordMatch;
       }
    

Probar la aplicación

En este procedimiento se prueba la aplicación. Se registrará un usuario, con lo que el nombre de usuario, el valor hash de contraseña y el valor salt se agregarán a la tabla Users de la base de datos UserAccounts. Después se iniciará sesión para el mismo usuario con el fin de asegurarse de que las rutinas de comprobación de contraseñas funcionan correctamente.

Para probar la aplicación

  • Vuelva al formulario de inicio de sesión y haga doble clic en el botón Logon para crear un controlador de eventos para gestionar eventos de clic sobre este botón.

  • Agregue el código siguiente al controlador de eventos de clic correspondiente al botón Logon para llamar al método VerifyPassword y mostrar un mensaje en función de si el nombre de usuario y la contraseña suministrados son válidos o no.

    bool passwordVerified = false;
       try
       {
       passwordVerified = VerifyPassword(txtUserName.Text,txtPassword.Text);
       }
       catch(Exception ex)
       {
       lblMessage.Text = ex.Message;
       return;
       }
       if (passwordVerified == true )
       {
       // The user is authenticated
       // At this point, an authentication ticket is normally created
       // This can subsequently be used to generate a GenericPrincipal
       // object for .NET authorization purposes
       // For details, see "How To: Use Forms authentication with GenericPrincipal    
       // objects
       lblMessage.Text = "Logon successful: User is authenticated";
       }
       else
       {
       lblMessage.Text = "Invalid username or password";
       }
    
  • En el menú Generar, haga clic en Generar solución.

  • En el Explorador de soluciones, haga clic con el botón secundario del mouse (ratón) en logon.aspx y, a continuación, haga clic en Ver en el explorador.

  • Escriba un nombre de usuario (User Name) y una contraseña (Password), y haga clic en Register (Registrar).

  • Utilice el Administrador corporativo de SQL Server para ver el contenido de la tabla Users. Debería aparecer una nueva fila para el nuevo nombre de usuario junto con un valor hash de contraseña generado.

  • Vuelva a la página Web de inicio de sesión, escriba de nuevo la contraseña y, después, haga clic en Logon (Iniciar sesión). Debería ver el mensaje "Logon successful: User is authenticated".

  • Escriba una contraseña no válida (con el mismo nombre de usuario). Debería ver el mensaje "Invalid username or password".

  • Cierre Internet Explorer.

Recursos adicionales

Para obtener más información, consulte los siguientes recursos:

Mostrar:
© 2015 Microsoft