Inserts:
insert into user_role (username, role, granted_date)
values ('admin','ADMIN',NOW());
insert into user_role (username, role, granted_date)
values ('customer','CUSTOMER',NOW());
Introducción
Seguridad en aplicaciones web
¿Qué es Spring Security?
Configurar Spring Security
Usar la autenticación por defecto
Configuración de seguridad
Crear configuración inicial de seguridad
¿Cómo funciona el BasicAuthenticationFilter?
Deshabilitar protección CSRF
Crear configuración de CORS
Aplicar requestMatchers
Crear autenticación en memoria
Aplicar requestMatchers con roles
Autenticación con BD
Crear usuarios en la base de datos
Implementar la interface UserDetailsService
Asignar roles a usuario
Aplicar authorities a los usuarios
Controlar métodos con Method Security
Seguridad con JWT
Añadir JWT al proyecto
Crear JWT cuando un usuario inicie sesión
Crear servicio para validar un JWT
Crear filtro para verificar el JWT
Aplicar filtro en la configuración
Próximos pasos
Auditoria de usuarios en la base de datos
¿Quieres un Curso de Microservicios con Java Spring?
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
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.
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:
User
.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).
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;
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:
Admin
al usuario admin
y un rol Customer
al usuario correspondiente.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.
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.
Aportes 8
Preguntas 4
Inserts:
insert into user_role (username, role, granted_date)
values ('admin','ADMIN',NOW());
insert into user_role (username, role, granted_date)
values ('customer','CUSTOMER',NOW());
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserRoleId implements Serializable {
private String username;
private String role;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof UserRoleId that)) return false;
return Objects.equals(username, that.username) && Objects.equals(role, that.role);
}
@Override
public int hashCode() {
return Objects.hash(username, role);
}
}
package com.platzi.pizza.persistence.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;
@Entity
@Table(name = "user_role")
@IdClass(UserRoleId.class)
@Getter
@Setter
@NoArgsConstructor
public class UserRoleEntity {
@Id
@Column(nullable = false, length = 20)
private String username;
@Id
@Column(nullable = false, length = 20)
private String role;
@Column(name = "granted_date", nullable = false, columnDefinition = "DATETIME")
private LocalDateTime grantedDate;
@ManyToOne
@JoinColumn(name = "username", referencedColumnName = "username", insertable = false, updatable = false)
private UserEntity user;
}
✅
package com.platzi.pizza.persistence.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
@Entity
@Table(name = "user")
@Getter
@Setter
@NoArgsConstructor
public class UserEntity {
@Id
@Column(nullable = false, length = 20)
private String username;
@Column(nullable = false, length = 200)
private String password;
@Column(length = 50)
private String email;
@Column(nullable = false, columnDefinition = "TINYINT")
private Boolean locked;
@Column(nullable = false, columnDefinition = "TINYINT")
private Boolean disabled;
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
private List<UserRoleEntity> roles;
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?