CodeGym /Cursos /Módulo 5. Spring /Roles de usuario y permisos de acceso: la anotación @Secu...

Roles de usuario y permisos de acceso: la anotación @Secured

Módulo 5. Spring
Nivel 17 , Lección 4
Disponible

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
    }
}
¡Las contraseñas deben estar obligatoriamente encriptadas! Usamos BCryptPasswordEncoder para eso.

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:

  1. Abre Postman o simplemente el navegador.
  2. Intenta acceder a /admin y 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

  1. Roles con el prefijo ROLE_. Spring Security espera que todos los roles empiecen por ROLE_. Si no lo haces, ¡te dará error! Por ejemplo, si en vez de ROLE_ADMIN pones solo ADMIN — no funcionará.
  2. Error 403 Forbidden. Si ves este error, asegúrate de que:
    • Está habilitado el soporte de @Secured mediante @EnableGlobalMethodSecurity(securedEnabled = true).
    • El rol del usuario está correctamente indicado (con el prefijo ROLE_).
  3. 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).

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION