En el mundo de las aplicaciones web, los usuarios no son simplemente abstractas "personas". A cada usuario se le puede asignar un rol que determina qué acciones puede realizar. Esto es un aspecto clave de la seguridad, porque asegura una separación estricta del acceso a datos y funcionalidades.
Imagina que estás desarrollando una aplicación bancaria: un cliente puede ver sus cuentas, transferir fondos, pero no puede, por ejemplo, generar reportes bancarios. En cambio, el administrador sí puede. Para gestionar esta separación a nivel de código se usa un sistema de acceso basado en roles. En Spring Security esto se hace con la anotación @Secured.
La anotación @Secured permite configurar el acceso a métodos o recursos en base a los roles de los usuarios. Se puede usar para restringir el acceso a nivel de services, controllers o incluso métodos de negocio concretos.
Documentación oficial: Spring Security: @Secured
Configuración de roles y seguridad usando @Secured
Vamos a ir paso a paso con esto.
1. Configurar el proyecto
Crearemos una aplicación simple con Spring Boot donde trabajaremos con usuarios y roles. Asegúrate de que tengas Spring Security activo.
Añadimos dependencias en pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Configuración de seguridad
Para usar @Secured necesitas habilitar el soporte de seguridad a nivel de métodos.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true) // Activamos el soporte para @Secured
public class SecurityConfig {
// En esta lección usamos la configuración integrada de usuarios (InMemoryUserDetailsManager),
// Veremos ejemplos más complejos con base de datos más adelante.
}
2. Definimos roles y usuarios
Para probar crearemos roles y usuarios en memoria (InMemoryUserDetailsManager).
Definimos usuarios y roles:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
public class UserConfig {
@Bean
public InMemoryUserDetailsManager userDetailsManager() {
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder().encode("admin123"))
.roles("ADMIN") // Rol de administrador
.build();
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder().encode("user123"))
.roles("USER") // Rol de usuario
.build();
return new InMemoryUserDetailsManager(admin, user);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // Hasheamos las contraseñas
}
}
3. Uso de @Secured en services
Creemos un servicio simple y limitemos el acceso a sus métodos según los roles.
Implementamos el servicio:
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Secured("ROLE_ADMIN") // Acceso solo para administradores
public String adminMethod() {
return "¡Hola, Administrador!";
}
@Secured("ROLE_USER") // Acceso solo para usuarios
public String userMethod() {
return "¡Hola, Usuario!";
}
}
Fíjate que los roles deben especificarse con el prefijo ROLE_. Por ejemplo, ROLE_ADMIN. Esto es el estándar de Spring Security.
4. Creamos un controller para probar
Ahora creamos un REST-controller que use nuestro service.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
private final MyService myService;
public MyController(MyService myService) {
this.myService = myService;
}
@GetMapping("/admin")
public String adminEndpoint() {
return myService.adminMethod();
}
@GetMapping("/user")
public String userEndpoint() {
return myService.userMethod();
}
}
5. Probamos la aplicación
Arranca la aplicación y prueba:
- Abre Postman o simplemente el navegador.
- Intenta acceder a
/adminy a/user.
Si has iniciado sesión como admin, el acceso a /admin estará permitido, y /user — denegado. Para user — al revés.
6. Añadir varios roles a un método
Si un método está disponible para varios roles, puedes pasarlos como un array:
@Secured({"ROLE_ADMIN", "ROLE_MANAGER"})
public String managerOrAdminMethod() {
return "¡Hola, Gerente o Administrador!";
}
Spring Security comprobará si el usuario pertenece al menos a uno de los roles indicados.
Particularidades y errores típicos
- Roles con el prefijo
ROLE_. Spring Security espera que todos los roles empiecen porROLE_. Si no lo haces, ¡te dará error! Por ejemplo, si en vez deROLE_ADMINpones soloADMIN— no funcionará. - Error
403 Forbidden. Si ves este error, asegúrate de que:- Está habilitado el soporte de
@Securedmediante@EnableGlobalMethodSecurity(securedEnabled = true). - El rol del usuario está correctamente indicado (con el prefijo
ROLE_).
- Está habilitado el soporte de
- No configures roles en los controladores sin motivo. Es mejor limitar la seguridad a nivel de services. Esto ayuda a minimizar la duplicación de lógica.
Aplicación práctica
Usar roles y permisos de acceso es una herramienta básica pero muy potente para gestionar acceso en aplicaciones. Se usa prácticamente en todos los sitios: desde pequeñas tiendas online hasta complejos sistemas corporativos. Por eso entender cómo funciona @Secured no es solo útil, es necesario.
Para casos más complejos veremos las anotaciones @PreAuthorize y @PostAuthorize en las siguientes lecciones — permiten configurar reglas de acceso más flexibles usando SpEL (Spring Expression Language).
GO TO FULL VERSION