lunes, 29 de julio de 2013

Restricción de Usuarios

A petición de un Usuario del Foro de C# les prepare un pequeño ejemplo sobre la restricción de usuarios en un sistema informático, en donde se valida la presencia del Usuario y la concordancia del Password proporcionado con los datos almacenados en la tabla Usuarios.

Para este ejercicio se usa estos datos contenidos en la Bd que esta adjunto al proyecto:
Usuarios

Tabla de configuración del Nivel de Acceso:
NivelAcceso

Teniendo en cuenta la información anterior procedamos a ver el código fuente del ejemplo:
Un de los aspectos mas importantes para poder utilizar el Login esta en el Main de la clase Program que es donde configuraremos que Formulario que deberá de arrancar como inicio, es decir, el formulario que hará la función de Logeo a la Bd.
   1: using System;
   2: using System.Windows.Forms;
   3:  
   4: namespace RestriccionDeUsuariosCSharp
   5: {
   6:     static class Program
   7:     {
   8:         /// <summary>
   9:         /// Punto de entrada principal para la aplicación.
  10:         /// </summary>
  11:         [STAThread]
  12:         static void Main()
  13:         {
  14:             //Application.EnableVisualStyles();
  15:             //Application.SetCompatibleTextRenderingDefault(false);
  16:             //Application.Run(new Form1());
  17:  
  18:             Application.EnableVisualStyles();
  19:             Application.SetCompatibleTextRenderingDefault(false);
  20:  
  21:             Login frm = new Login();
  22:             frm.ShowDialog();
  23:  
  24:             if (frm.DialogResult == DialogResult.OK)
  25:                 Application.Run(new Form1());
  26:         }
  27:     }
  28: }

El Formulario Login será el encargado de realizar la autenticación a la Bd:
Login

Dentro procedemos a crear las Funcion autenticar:

   1: /// <summary>
   2: /// Funcion encargada de validar la existencia del Usuario y Password
   3: /// </summary>
   4: /// <Autor>Jose Luis Garcia Bautista</Autor>
   5: /// <param name="usuario"> Nombre del usuario en la BD</param>
   6: /// <param name="password"> Password perteneciente al Nombre de usuario proporcionado</param>
   7: /// <returns>True si ambos datos conincide con algun registro de la Bd</returns>
   8: public static bool Autenticar(string usuario, string password)
   9: {
  10:     //Utilizamos el Bloque Using...end Using para administrar la conexion
  11:     //este se encarga de cerrar la conexion y destruir todos los objetos encerrados en el
  12:     using (SqlCeConnection cnx = new SqlCeConnection(ConfigurationManager.ConnectionStrings["UserConnectionString"].ToString()))
  13:     {
  14:         //
  15:         //Abrimos la conexion a la Bd
  16:         //
  17:         cnx.Open();
  18:         //
  19:         //Creamos la Consulta SQl utilizando parametros, en donde unicamente recuperaremos el NivelDeAcceso
  20:         //con el que cuenta el Usuario siempre cuando Exista y se hayan proporcionado las credenciales validas
  21:         //
  22:         const string sqlAction = "SELECT NivelAcceso FROM Usuarios WHERE Usuario = @username AND Password = @pass";
  23:         //
  24:         //Creamos el objento Command propio del motor de la Bd que estamos usando
  25:         //
  26:         SqlCeCommand cmd = new SqlCeCommand(sqlAction, cnx);
  27:         //
  28:         //Asignamos valores a la coleccion de parametros
  29:         //
  30:         cmd.Parameters.AddWithValue("@username", usuario);
  31:         cmd.Parameters.AddWithValue("@pass", password);
  32:         //
  33:         //Recuperamos la cantidad de registros coincidentes con el Usuario y Password por logica
  34:         //solo podremos recuperar un solo registro
  35:         //
  36:         int tipoUsuario = Convert.ToInt32(cmd.ExecuteScalar());
  37:         //
  38:         //Si el tipodeusuario es Mayor a cero significa que la Validacion fue cumplida y el usuario
  39:         //tiene un nivel de acceso
  40:         //
  41:         if (tipoUsuario > 0)
  42:         {
  43:             //
  44:             //Enviamos el Nivel de acceso a la propiedad NivelAcceso de la Clase Usuarios
  45:             //
  46:             Usuario.NivelAcceso = tipoUsuario;
  47:             //
  48:             //retornamos True ya que la validacion a sido Exitosa
  49:             //
  50:             return true;
  51:         }
  52:     }
  53:     //
  54:     //Si la validacion no fue cumplica retornamos False para evitar continuar con el proceso
  55:     //
  56:     return false;
  57: }

Utilizamos la función Autenticar:

   1: private void btnaceptar_Click(object sender, EventArgs e)
   2: {
   3:     try
   4:     {
   5:  
   6:         //Mandamos a llamar a la funcion Autenticar mandandole los parametros requeridos
   7:         //Autenticar(ByVal usuario As String, ByVal password As String)
   8:  
   9:         {
  10:             if (Autenticar(txtusuario.Text.Trim(), txtpassword.Text.Trim()))
  11:             {
  12:                 //Si el resultado de la funcion es True entonces enviamos comor resultado un Ok
  13:                 DialogResult = DialogResult.OK;
  14:             }
  15:             else
  16:             {
  17:                 //Si la funcion autenticar envio un False entonces mostramos el mensaje y mandamos un Abort
  18:                 MessageBox.Show("Usuario o Password no validos");
  19:                 DialogResult = DialogResult.Abort;
  20:             }
  21:         }
  22:     }
  23:     catch (Exception ex)
  24:     {
  25:         MessageBox.Show(string.Format("Error : {0}", ex.Message), "Error inesperado", MessageBoxButtons.OK, MessageBoxIcon.Error);
  26:     }
  27: }

Dentro del Form1 procedemos a validar el Nivel de acceso del usuario para habilitar e inhabilitar las opciones del Menú:

   1: using System;
   2: using System.Windows.Forms;
   3:  
   4: namespace RestriccionDeUsuariosCSharp
   5: {
   6:     public partial class Form1 : Form
   7:     {
   8:         public Form1()
   9:         {
  10:             InitializeComponent();
  11:         }
  12:  
  13:         private void Form1_Load(object sender, EventArgs e)
  14:         {
  15:             //Preguntamos por el contenido de la variable publica
  16:             //NivelAcceso contenido en la clase Usuario
  17:  
  18:             {
  19:                 switch (Usuario.NivelAcceso)
  20:                 {
  21:                         //
  22:                         //Opciones validar para un Administrador
  23:                         //
  24:                     case 1:
  25:                         //Configuramos las opciones
  26:                         MenuInvitado.Enabled = false;
  27:                         MenuMiembro.Enabled = false;
  28:                         break;
  29:  
  30:                         //
  31:                         //Opciones validas para un Miembro
  32:                         //
  33:                     case 2:
  34:                         MenuAdmisnitrador.Enabled = false;
  35:                         MenuMiembro.Enabled = false;
  36:                         break;
  37:  
  38:                         //
  39:                         //Opciones validas para un Invitado
  40:                         //
  41:                     case 3:
  42:                         MenuInvitado.Enabled = false;
  43:                         MenuAdmisnitrador.Enabled = false;
  44:                         break;
  45:                 }
  46:             }
  47:         }
  48:     }
  49: }

Si el proceso de Login fue cubierto satisfactoriamente podremos ver el formulario Form1 con las restricciones configuradas:

Menu

El ejemplo proporcionado cuenta con muchas opciones de mejora como.
  • No utilizar una propiedad publica para compartir del Nivel de acceso de Usuario y en cambio usar el Patron Singleton para compartir información en todo el proyecto sin el riesgo de que este sea cambiado por una instancia diferente, es decir, únicamente se instancia una sola vez y nada mas. Para mas información del Patron Singleton: El Patrón Singleton

  • El uso de un Algoritmo de encriptación como Hash para poder encriptar la información de Password dando con esto una mayor seguridad a la aplicación, para mayor informacion: Desmitificando la Encriptación (Parte II)
Esas son las dos principales carencias del Ejercicio, debido a que esta primera entrega únicamente tiene como objetivo orientar sobre el proceso de Login pero, en una entrega posterior se agregaran estas dos funcionalidades.

Nota: El proyecto fue desarrollado en Vs2010 usando una Bd SqlCompact V3.5 y Framework 4.0

11 comentarios:

  1. muchas gracias por la ayuda, ya logre realizar el ejemplo, pero si lo quiero aplicar en un menu creado con ribon y en ribon no tiene o no acepta enabled, como puedo hacerle?

    de antemano Gracias.
    Saludos

    ResponderEliminar
  2. Hola:
    Me alegro que te haya servido, con respecto al Ribbon te comento que aun no trabajo con el asi que desconosco las propiedades con las que cuenta pero estoy casi seguro que cuenta con la propiedad Visible, esa tambien podria servirte. Si tienes manera de enviarme el control con todo gusto hago unas pruebas y te comento.

    saludos!

    ResponderEliminar
  3. Gracias, pero si fuera con checkbox, donde tu al momento de crear un usuario, ahi mismo o la lado derecho le va asignando sus privilegios.
    Rigoberto Estrella

    ResponderEliminar
  4. Hola:
    Todo es posible, muy pronto subiré un nuevo articulo en donde por medio de un formulario de administración se le concedan o eliminen privilegios a un usuario, ademas de utilizar una contraseña con hash...

    Saludos desde Monterrey, Nuevo León, México!

    ResponderEliminar
  5. Hola amigo José muchas gracias por tus aportes espero que sigas asi y que tengas muchos existos en la vida:
    TENGO UNA CONSULTA (Quizas facil para unos y dificil para mi que no se casi nada de esto)
    Quize probar tu proyecto con Visual studio 2012 y me sale este error :

    Advertencia 1 El proyecto hace referencia a una versión anterior de SQL Server Compact que no tiene compatibilidad con el diseñador en la versión actual de Visual Studio. Para continuar sin compatibilidad con el diseñador, descargue SQL Server Compact 3.5 del centro de descarga de Microsoft (http://go.microsoft.com/fwlink/?LinkId=229598). Para actualizar los activos a SQL Server Compact 4.0 y habilitar la compatibilidad con el diseñador, abra el proyecto y use el cuadro de diálogo Agregar conexión para crear una conexión a la base de datos.

    Que puedo hacer para solucionarlo y que el proyecto se pueda ejecutar sin complicaciones

    ResponderEliminar
    Respuestas
    1. Hola:

      Gracias por tus buenos deseos!

      El error que te marca es porque con la versión 2012 del Visual Studio ya no viene el SqlCompact en la versión 3.5 sin embargo se incluye la versión 4.0 que entiendo yo debería de ser mejor ya que con la liberación de nuevas versión normalmente se corrigen algunos bugs que se van encontrando en la versión previa (también podrían inyectarseles nuevos).

      Para solucionar tu problema, podrías descargarte e instalar la versión 3.5 del SQlCe de esta liga:

      http://www.microsoft.com/es-mx/download/details.aspx?id=5783

      Después de eso no deberías de tener ningún problema.

      Eliminar
    2. Muy buenas tardes amigo José Luis Garcia Bautista muchas gracias por tu tiempo dedicado y a tu pronta respuesta no te lo pude agradecer antes por motivos de tiempo pero ahora que tengo la oportunidad no la queria dejar pasar y te lo agradezco por tu pronta respuestay te manifiesto que solucione el pequeño inconveniente.
      Pasando a otro punto quisiera ver si me puedes ayudar con este tema en el cual necesito ayuda se trata sobre el obtener el tipo de cambio en visual basic 6.0 de esta página http://www.sunat.gob.pe/cl-at-ittipcam/tcS01Alias. yo e avanzada hasta donde pude pero ya no se que mas hacer el tema para no hacer tan extenso el comentario esta aca http://www.lawebdelprogramador.com/foros/Visual_Basic/1441122-Obtener_tipo_de_cambio_de_sunat.html

      Eliminar
  6. buenas tarde yo queria hacerle una consulta es que quiero saber como se hace login en 3 capas en c#

    ResponderEliminar
  7. o como hacer login en 3 capas en visual studio 2010 en c#

    ResponderEliminar
  8. Hola Jose Luis Disculpa Quiero bajar tu proyecto pero no puedo podras enviarmelo a mi correo luis_zevallos@hotmail.com
    desde Peru

    ResponderEliminar
  9. Hola Jose Luis Disculpa Quiero bajar tu proyecto pero no puedo podras enviarmelo a mi correo
    carrlosm04@gmail.com

    ResponderEliminar

Deja un comentario si el articulo fue de utilidad.