Curso de Spring Boot | Roles 1

Curso de Spring Boot
Roles

Curso de Spring Boot | Roles 2

En esta lección, aprenderemos a implementar un sistema de roles en una aplicación Spring Boot utilizando Spring Security. Exploraremos cómo restringir accesos a endpoints según los roles asignados a los usuarios, así como la estructura de entidades del modelo de usuarios y roles.

En el SecurityConfig podemos establecer que el endpoint /user/test sólo sea accesible si tienes el rol de ADMIN.

package com.app.config;
...
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 
 http.csrf(csrf -> csrf.disable());
 http.authorizeHttpRequests((authorizeRequests) -> {
   
 authorizeRequests
 .requestMatchers("/user/test").hasAnyAuthority("ADMIN")
 .anyRequest().authenticated();
 }).httpBasic(withDefaults());
 return http.build();
}
...

📌 Puntos clave:

  • http.csrf().disable(); desactiva la protección contra CSRF.
  • authorizeHttpRequests() define las restricciones de acceso.
  • .requestMatchers("/user/test").hasAuthority("ADMIN") permite el acceso solo a usuarios con el rol ADMIN.
  • .anyRequest().authenticated(); requiere autenticación para cualquier otro endpoint.

Entidades del modelo

package com.app.model;

@Getter
@Setter
@Entity
@Table(name = "user")
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Para generar números autoincrementados
    private long id;
    private String username;
    private String password;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = CascadeType.REMOVE)
    private List<RoleUserAssociation> lstRoleUserAssociation;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
             return roles.stream().map(role -> new SimpleGrantedAuthority(role.getRoleName()))0.collect(Collectors.toList());
    }
}

✅ Implementa UserDetails, requerido por Spring Security.
✅ Contiene credenciales del usuario y una lista de roles asociados.

package com.app.model;

@Entity
public class Role implements Serializable {
 private static final long serialVersionUID = 198355926937292762L;

 public static final String ADMIN_ROLE = "ADMIN";
 public static final String ROLE1 = "ROLE1";


 public static final String LST_USER = "lstUser";

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;

 /**
  * Nombre del rol
  */
 private String roleName;

 @OneToMany(mappedBy = "role", fetch = FetchType.EAGER)
 private List<RoleUserAssociation> lstRoleUserAssociation;

 public Role() {
  roleName = "";
  lstRoleUserAssociation = new ArrayList<RoleUserAssociation>();
 }

 public Role(String roleName) {
  if (roleName == null) {
   throw new IllegalArgumentException("El nombre del rol no puede ser nulo");
  }

  this.roleName = roleName;
  lstRoleUserAssociation = new ArrayList<RoleUserAssociation>();
 }

 public boolean equals(Object obj) {
  boolean equal = false;

  if (obj instanceof Role) {
   Role role = (Role) obj;

   if (role.roleName.equals(roleName)) {
    equal = true;
   }
  }

  return equal;
 }
}

✅ Define roles disponibles en la aplicación.
✅ Contiene una constante para cada rol.

package com.app.model;
...
@Entity
@Table(name = "roleUserAssociation")
public class RoleUserAssociation implements Serializable {
 private static final long serialVersionUID = 7350135545320698807L;

 @Id
 @EmbeddedId
 private RoleUserAssociationId id;

 @ManyToOne
 @JoinColumn(name = "user_id", updatable = false, insertable = false, referencedColumnName = "id")
 private User user;

 @ManyToOne
 @JoinColumn(name = "role_id", updatable = false, insertable = false, referencedColumnName = "id")
 private Role role;

 public RoleUserAssociation() {
 }

 public RoleUserAssociation(User user, Role role) {
  this.user = user;
  this.role = role;
  id = new RoleUserAssociationId(user.getId(), role.getId());
 }
}
package com.app.model;
...
public class RoleUserAssociationId implements Serializable {

 private static final long serialVersionUID = -426631449303803949L;

 private Long user_id;
 private Long role_id;
 
 
 public RoleUserAssociationId() {
 }

 public RoleUserAssociationId(Long user_id, Long role_id) {
  this.user_id = user_id;
  this.role_id = role_id;
 }
}

✅ Relación muchos a muchos entre usuarios y roles.
✅ Usa una clave compuesta RolesUserAssociationId para la asociación.

Controlador

package com.app.controllers;

@RestController
@RequestMapping("/user")
public class UserController {

 @Autowired
 private UserRepository userRepository;

 @GetMapping("/test")
 public ResponseEntity<String> test() {
  return ResponseEntity.ok().body("{\"resp\":\"Archivo cargado con éxito\"}");

 }
}

@RequestMapping("/user") define el prefijo de la URL.
@GetMapping("/test") maneja la petición GET /user/test.
✅ Devuelve un JSON de respuesta.