jueves, 8 de julio de 2010

Inicio de sesión con cifrado MD5

Que tal amigos, recién he creado este blog donde abordaré mis experiencias (q apenas comienzan) en el mundo de la programación, esperó contar con sus comentarios para mejorar el blog, la verdad es que soy nuevo blogger… bueno comencemos:

Para mi primer blog escogí algo sencillo como lo es un Inicio de Sesión entre un form escrito en C# y una BD en SQL Server 2008.

La Base de Datos usada se nombra escuela, y contiene la tabla usuarios con el campo userID para almacenar el nombre de usuario y el campo pass para archivar la contraseña cifrada con el algoritmo MD5 (por lo cual es varbinary), je claro hay que ponerle un poco de seguridad al login:


create database escuela
go
use escuela
go


create table usuarios(
userID varchar(16) primary key,pass varbinary(max)
)
go


Para agregar los usuarios utilizo el clásico insert into de SQL, y la función HASHBYTES(algoritmo,frase) que cifra según el algoritmo establecido la frase que nosotros deseemos.
insert into usuarios(userID,pass) values('admin',HASHBYTES('MD5','hola'));
go


insert into usuarios(userID,pass) values('erick',HASHBYTES('MD5','123456'));
go

queda cifrada la cadena de forma binaria como podemos percatarnos en la siguiente consulta a la tabla alumnos:



Muy bien con esta BD basta para la demostración del ejemplo de inicio de sesión que pretendo.

Ahora toca el turno de crear el formulario que se conectará con la BD para la autenticación de usuarios.
Agregué 2 Label y dos TexBox



Cambiando un poco la apariencia del Form basándome en el siguiente enlace utilizó la imagen fondo.png para obtener el siguiente formulario:




Incluiremos el archivo App.config para incluir la cadena de conexión con SQL Server, para ello usamos el menú Proyecto/Agregar nuevo elemento…

Y en el cuadro posterior seleccionamos el Archivo de Configuración de aplicaciones, y lo agregamos.



Dentro de este archivo agregamos la cadena de conexión con el SQL Server quedando de la siguiente manera:


<
configuration>



      <
connectionStrings>
            <add name="miConexion"
                   connectionString="Integrated Security=SSPI; Initial Catalog=escuela; Data Source=."
                   providerName="System.Data.SqlClient" />
      connectionStrings>
configuration>


De regreso al código del formulario incluimos la librería para el acceso a datos a través de System.Data.SqlClient y para el cifrado MD5 de la contraseña utilizamos System.Security. Cryptography:
using System.Data.SqlClient;
using System.Security.Cryptography;
Para utilizar la cadena de conexión que añadimos en el archivo app.config hay que agregar otra referencia desde el menú Proyecto/Agregar referencia
en el cuadro de diálogo que se muestra añadimos System.Configuration


y también hay que importarla desde el código para poder utilizarla:
using System.Configuration;
Para evitar SQLi valido la entrada de caracteres en las cajas de texto y sólo se permiten Letras, dígitos, y los caracteres de control, el método es el siguiente y hay que asignarlo al evento KeyPress:


private void caja_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (Char.IsLetterOrDigit(e.KeyChar))
            {
                e.Handled = false;
            }
            else if (Char.IsControl(e.KeyChar))
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }


Ahora en el evento Load del formulario asignamos el metodo caja_KeyPress al evento KeyPress de las cajas de texto:
private void Form1_Load(object sender, EventArgs e)
        {
            this.userTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.caja_KeyPress);
            this.passTextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.caja_KeyPress);
        }


Recordando que en la BD almacenamos la contraseña cifrada con el algoritmo MD5, desde C# también debemos crear una función para cifrar la contraseña escrita por el usuario y enviar la sumatoria hash para compararla con lo que se encuentra en la BD.
Para ello creamos la función cifrar que recibe una cadena y regresa un arreglo de bytes que representan la cadena cifrada con MD5, que con la ayuda de Ramms se simplifica así:
private byte[] cifrar(string cadena)
        {
            MD5 md5 = new MD5CryptoServiceProvider();


            byte[] resultado = md5.ComputeHash(Encoding.Default.GetBytes(cadena));
            return resultado;
        }



Para el botón de iniciar sesión colocamos el siguiente código al evento click:


Int32 resultado = 0;
            //crea la conexión usando ConfigurationManager para obtener la cadena de conexión del archivo app.config
            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["miConexion"].ConnectionString);
            //crea el comando para comparar el usuario y contraseña en la BD.
            SqlCommand cmd = new SqlCommand("select count(*) from usuarios where userID like @userID and pass=@password;", con);
            //agrega el parámetro @userID
            cmd.Parameters.AddWithValue("@userID", userTextBox.Text);
            //agrega el parámetro @password, con la contraseña cifrada en binario mediante la función cifrar
            cmd.Parameters.AddWithValue("@password", cifrar(passTextBox.Text));


            //Ejecuta la consulta y obtiene un valor para determinar si se encontro el usuario en la BD
            con.Open();
            resultado=Int32.Parse(cmd.ExecuteScalar().ToString());
            con.Close();
           
            if (resultado>0)
            {
                MessageBox.Show ("Bienvenido ");

                this.Close();
            }
            else
            {
                MessageBox.Show("Por favor,Verifica la combinación de usuario y contraseña.");
                userTextBox.Clear();
                passTextBox.Clear();
                userTextBox.Focus();

         }




Bueno sólo falta cambiar la apariencia de los botones con imágenes, que tanto le interesa a Juan Miguel,...

Espero que esto le sirva a alguien, si lo sé faltó control de excepciones y demás cosas, bueno comenten por favor para que esto vaya mejorando…