Creando un diálogo de Login con SwingX, Spring y JPA: Introducción


En esta serie veremos cómo implementar un mecanismo de autenticación de usuarios haciendo foco en la reutilización de componentes tanto de back-end como de front-end. Originalmente el alcance se reducía a presentar el componente JXLoginPane y el framework de autenticación de la extensión SwingX desarrollada por el equipo de Swinglabs, el cual está orientado orientado mayormente al front-end pero que nos deja parte de la implementación de back-end a los desarrolladores. Finalmente decidí ampliar el scope y abarcar aspectos de base de datos, uso de JPA y Spring para manejo de transacciones e inyección de dependencias. A continuación los requisitos para desarrollar el ejemplo, una breve introducción del motivo de esta serie de entradas, y la presentación del framework de autenticación de SwingX.

Requerimientos

Para desarrollar el ejemplo utilizaremos las siguientes herramientas y librerías. Para quienes utilicen Maven, más adelante compartiré el pom.xml con las dependencias correspondientes.

  • MySQL 5.6 Server Community Edition
  • MySQL JDBC Connector 5.1.6
  • Eclipselink JPA 2.5.2
  • SwingX 1.6.4
  • Spring Framework 4.1.6

Introducción

En la medida que nuestras aplicaciones van creciendo en complejidad y la información que manejan se torna sensible, va siendo hora de implementar algún mecanismo de inicio de sesión o login. Este mecanismo puede ser más o menos complejo, dependiendo de la aplicación en sí, pero en líneas generales sigue este patrón:

  • Un cuadro de diálogo que captura el nombre de usuario y contraseña.
  • Un proceso que valida la autenticidad de estas credenciales:
    • Si las credenciales son válidas, la aplicación continúa su ejecución.
    • Si no, se informa al usuario para que vuelva a intentar.

A esto podemos sumarle detalles de implementación más complejos como manejo de roles de usuario, múltiples servidores redundantes para autenticación, bloqueo preventivo de la cuenta de usuario cuando se intenta acceder con una contraseña inválida más de un número límite de veces, encripción o hashing de contraseñas, permitir “caché” o guardado local de usuarios y passwords para ayudar en el proceso de autenticación, etcétera.

Todos estos detalles hacen que un simple diálogo de login se torne complejo en cuestión de minutos. Generalmente hablando este hecho puede lograr que cada aplicación que desarrollemos tenga una implementación propia y que reutilicemos poco o nada de otras aplicaciones en lo que respecta al login. Sin embargo, los detalles de implementación no alteran la esencia y el proceso en sí sigue siendo simple: capturar datos, procesarlos, devolver un resultado.

Partiendo de esta premisa, el equipo de Swinglabs  ofrece un framework de autenticación e inicio de sesión en el proyecto SwingX, diseñado para aislar correctamente las responsabilidades en este proceso y permitirnos ajustarlo a nuestra medida, yreutilizando gran parte de nuestro código. Este framework gira en torno al componente JXLoginPane y consta de las siguientes partes:

  • JXLoginPane: es un componente visual que consiste en un panel con controles básicos para capturar los datos de inicio de sesión por parte del usuario. Este panel incluye un encabezado, un text field para el nombre de usuario, un password field para la contraseña, un combo box para seleccionar el servidor sobre el cual autenticar, y un check box para guardar el nombre de usuario y/o contraseña en caché.
  • LoginService: clase abstracta que debe implementar la lógica de autenticación de las credenciales ingresadas en el componente JXLoginPane. Internamente mantiene una lista con objetos que implementan la interfaz LoginListener, los cuales son notificados mediante LoginEvents durante todo el proceso: login iniciado, cancelado, exitoso o fallido.
  • LoginListener: esta interfaz ofrece un contrato para “escuchar” o atender eventos durante el proceso de login y actuar en consecuencia. Al igual que la mayoría de los listeners en Swing, también tiene su “adapter”: LoginAdapter.
  • PasswordStore: clase abstracta cuya finalidad es la de almacenar las contraseñas ingresadas por los usuarios en una especie de caché, con el objetivo de ayudar en el proceso de login. El verdadero mecanismo y la forma de persistencia de las contraseñas se deja a cargo de las implementaciones concretas. De este modo podemos guardar contraseñas en un archivo plano local, una base de datos auxiliar, un archivo properties o xml, etcétera.
  • UserNameStore: igual que PasswordStore pero para nombres de usuario.

Cada una de estas piezas cumple una función determinada y nos permite dividir responsabilidades en forma coherente y cohesiva. A los efectos de no perdernos en esta maraña de clases, interfaces y responsabilidades divididas, diremos que el 90% de nuestro trabajo consiste en implementar correctamente el siguiente método abstracto:

public abstract class LoginService {
    private String userName, password;
    private boolean isAuthenticated;
    ...
    public abstract boolean authenticate(String name, char[] password, String server) throws Exception;
    ...
}

El método authenticate(..) de la clase LoginService es el encargado de efectuar la lógica del proceso de autenticación, lo más complejo, dejando la interacción del usuario a cargo del componente JXLoginPane. A continuación crearemos nuestra implementación partiendo desde la definición de la base de datos contra la cual autenticar, nuestra implementación de la clase LoginService y la interacción con JXLoginPane.

Continuará…

En la siguiente entrada comenzaremos por la base de datos de nuestro ejemplo, incluyendo algunos aspectos de seguridad, veremos cómo hacer el mapeo objeto-relacional correspondiente y finalmente implementaremos la capa DAO de nuestra aplicación. Más adelante veremos la capas de Servicio y la Vista, el uso de Spring y el componente JXLoginPane.

 

Anuncios

3 pensamientos en “Creando un diálogo de Login con SwingX, Spring y JPA: Introducción

  1. hernán

    Hola Delcio, has vuelto al ruedo, buenísimo, ya era hora, ja.

    El tema es muy interesante, justamente estaba trabajando con un pequeño ejemplo de REST service en Android (un CRUD que ya tengo completo), y quería agregarle autenticación a las operaciones. El lado servidor lo tengo hecho con Spring MVC (y Spring JDBC Template en la base, pero usé eso para empezar ‘de abajo’, la intención era colocarle JPA en un futuro cercano). Veremos qué puedo extrapolar de lo que propongas, así que acá estamos, preparados para el ejercicio.

    Saludos!

    Me gusta

    Responder
    1. Delcio Amarillo Autor de la entrada

      Hola Hernán! Muchas gracias por seguir el blog 😀 Si, estuve en stand-by por un buen tiempo, preparando algún ejemplo decente que valga la pena compartir.

      Espero que esta serie sea de utilidad, pero te adelanto que el uso de Spring va a ser bastante básico, sólo inyección de dependencias y manejo de transacciones. En un mini curso que hice vi que tiene opciones para trabajar con JDBC y JPA de forma tal que podés hacer un CRUD en 5 minutos. En lo personal me pareció una buena característica pero prefiero no usarla y apegarme más al estándar, haciendo los CRUD con EntityManager. Soy más clásico en ese sentido jaja.

      Me gusta

      Responder
  2. hernán

    Ah, bueno, lo aprovecharemos igual. Sí, Spring tiene cosas que están demasiado automatizadas, Spring DATA (o algo así, ahora no recuerdo bien) practicamente te automatiza toda la generación de datos. Yo también hice un curso corto hace unos meses, pero recién hace poco conseguí un hosting y me puse a trabajar en ejemplos concretos.

    La verdad es que está muy bueno, pero al igual que a muchos, no me termina de convencer la excesiva ‘caja negra’ que propone para algunos módulos. Lo que está muy bueno es que con un Tomcat hacés cosas para las que sería necesario un GlassFish.

    Así que vendrá bien ver un ejemplo con el uso de EntityManager, que tampoco domino ni de lejos.

    Saludos!

    Me gusta

    Responder

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s