Asignación de Roles y Permisos en Spring Security

Clase 14 de 23Curso de Java Spring Security: Autenticación y Seguridad Web

Resumen

¿Cómo gestionar roles de usuario en Spring con Hibernate?

En el desarrollo de aplicaciones web seguras, la gestión de usuarios y roles es una pieza fundamental. Esta guía te proporciona una base sólida para implementar y administrar roles de usuario en tus aplicaciones usando Spring y Hibernate. Exploraremos cómo crear y asignar roles a usuarios dentro de una base de datos MySQL y cómo conectar este sistema a un User Detail Service en Spring.

¿Cómo crear la tabla de roles de usuario?

Para comenzar, vamos a crear una tabla en MySQL que gestione los roles. Esta tabla se llamará User_Role y estará relacionada con la tabla User. Aquí tienes una idea de cómo debería ser su estructura:

  • Username: Viene de la tabla User.
  • Role: Será uno de los roles asignados.
  • Granted Date: Indica desde cuándo el rol ha sido asignado.

Puedes crear esta tabla usando Hibernate o directamente con un script SQL en tu base de datos MySQL. Este enfoque asegura que cada usuario pueda tener distintos roles, reflejando una relación de uno a muchos (one-to-many).

¿Cómo implementar las entidades en tu proyecto?

Dentro de tu proyecto de Spring, deberás implementar la entidad UserRoleEntity. Aquí es donde definiremos cómo se relacionan los usuarios con los roles:

public class UserRoleEntity {
    @IdClass(UserRoleId.class)
    private String username;
    private String role;
    private LocalDate grantedDate;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private UserEntity user;
    
    // Getters, setters, equals, and hashCode methods
}

La entidad UserRoleEntity implementa una clave primaria compuesta por username y role, reflejando su naturaleza de relación en la base de datos.

En UserEntity, incorpora una lista de UserRoleEntity anotada con @OneToMany. Asegúrate de configurar la carga FetchType.EAGER para que los roles se carguen automáticamente al recuperar un usuario.

@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
private List<UserRoleEntity> roles;

¿Cómo asignar roles y verificar el acceso?

Una vez que la aplicación está configurada y la tabla creada, es hora de asignar roles a usuarios. Puedes realizar esta operación directamente en MySQL Workbench:

  1. Asigna el rol Admin al usuario admin y un rol Customer al usuario correspondiente.
  2. Asegúrate de utilizar la función now() de MySQL para registrar correctamente la fecha actual en Granted Date.

Finalmente, en tu implementación del UserDetailService, reemplaza la lista de roles inicial con los roles obtenidos de la base de datos. Convierte los roles a un arreglo de cadenas de caracteres, utilizándolos para autenticar y autorizar a los usuarios.

String[] roles = userEntity.getRoles()
    .stream()
    .map(UserRoleEntity::getRole)
    .toArray(String[]::new);

De esta manera, puedes controlar el acceso a los diferentes endpoints de tu API, asegurándote de que solo aquellos usuarios con los permisos necesarios puedan realizar ciertas acciones.

¿Qué hacer en caso de bloqueos de cuenta?

Además de asignar roles, tienes la capacidad de bloquear usuarios temporalmente si fuera necesario. Esto se gestiona mediante una propiedad locked, la cual, al activarse, impide que el usuario acceda al sistema aunque sus credenciales sean correctas:

UPDATE user SET locked = 1 WHERE username = 'admin';

Esta funcionalidad es crucial para asegurar tu aplicación contra accesos indebidos o para manejar situaciones de seguridad específicas.

Con esta estructura, aseguras que tu aplicación no solo sea segura, sino también flexible, permitiendo una administración detallada de los recursos y accesos según los roles de usuario establecidos.