Capítulo 4: Curso Complementario
🎯 Objetivos
- Profundizar los conceptos con los cursos complementarios
- Explorar los módulos 22 a 28 sobre seguridad
- Dominar los aspectos avanzados del proyecto
📚 Recurso Principal
Curso Complementario
Todos los cursos complementarios están disponibles en el repositorio:
Enfoque particular en los módulos 22 a 28 para la parte de seguridad.
🗂️ Estructura de los Cursos
La carpeta cours/ contiene una serie de módulos progresivos:
Vista general
| Módulo | Tema | Descripción |
|---|---|---|
| 01-10 | Fundamentos | Bases del proyecto, configuración, arquitectura |
| 11-18 | Seguridad Detallada | Spring Security paso a paso (ver Capítulo 5) |
| 19-21 | API Avanzada | Endpoints complejos, validación |
| 22-28 | Seguridad Avanzada | JWT, roles, protección de rutas |
🔐 Enfoque: Módulos 22 a 28 (Seguridad)
Estos módulos cubren los aspectos avanzados de la seguridad:
Módulo 22: Introducción a Spring Security
- Configuración básica
- Filtros de seguridad
- AuthenticationManager
Módulo 23: Autenticación por Formulario
- UserDetailsService
- PasswordEncoder
- Almacenamiento de usuarios
Módulo 24: JWT (JSON Web Tokens)
- Generación de tokens
- Validación de tokens
- Estructura de un JWT
// Structure d'un JWT
{
"header": {
"alg": "HS256",
"typ": "JWT"
},
"payload": {
"sub": "user@example.com",
"iat": 1609459200,
"exp": 1609545600,
"roles": ["USER", "ADMIN"]
},
"signature": "..."
}
Módulo 25: Filtros de Autenticación
- JwtAuthenticationFilter
- Cadena de filtros de Spring Security
- OncePerRequestFilter
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
// Valider le token et authentifier
}
filterChain.doFilter(request, response);
}
}
Módulo 26: Autorización basada en Roles
- @PreAuthorize
- @Secured
- hasRole() y hasAuthority()
@RestController
@RequestMapping("/api/admin")
public class AdminController {
@GetMapping("/leads")
@PreAuthorize("hasRole('ADMIN')")
public List<LeadDto> getAllLeads() {
return leadService.getAllLeads();
}
@DeleteMapping("/leads/{id}")
@PreAuthorize("hasRole('ADMIN')")
public void deleteLead(@PathVariable Long id) {
leadService.deleteLead(id);
}
}
Módulo 27: Protección de Rutas
- Configuración SecurityFilterChain
- Endpoints públicos vs protegidos
- CORS y CSRF
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.authorizeHttpRequests(auth -> auth
// Endpoints publics
.requestMatchers("/api/contact").permitAll()
.requestMatchers("/api/auth/**").permitAll()
// Endpoints protégés
.requestMatchers("/api/admin/**").hasRole("ADMIN")
// Tout le reste nécessite authentification
.anyRequest().authenticated()
)
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
Módulo 28: Pruebas de Seguridad
- @WithMockUser
- Pruebas de autorización
- Pruebas de autenticación
@SpringBootTest
@AutoConfigureMockMvc
class SecurityTests {
@Autowired
private MockMvc mockMvc;
@Test
void adminEndpoint_withoutAuth_returns401() throws Exception {
mockMvc.perform(get("/api/admin/leads"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(roles = "ADMIN")
void adminEndpoint_withAdmin_returns200() throws Exception {
mockMvc.perform(get("/api/admin/leads"))
.andExpect(status().isOk());
}
@Test
void publicEndpoint_withoutAuth_returns200() throws Exception {
mockMvc.perform(post("/api/contact")
.contentType(MediaType.APPLICATION_JSON)
.content("{...}"))
.andExpect(status().isOk());
}
}
📋 Conceptos Clave Abordados
Arquitectura de Seguridad
┌─────────────────────────────────────────────────────────┐
│ Requête HTTP │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Security Filter Chain │
│ ┌───────────────────────────────────────────────────┐ │
│ │ 1. CorsFilter │ │
│ │ 2. CsrfFilter (désactivé pour API) │ │
│ │ 3. JwtAuthenticationFilter ◄─── Valide le token │ │
│ │ 4. UsernamePasswordAuthenticationFilter │ │
│ │ 5. AuthorizationFilter ◄─── Vérifie les rôles │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Controller │
└─────────────────────────────────────────────────────────┘
Flujo de Autenticación JWT
🛠️ Ejercicios Prácticos
Ejercicio 1: Añadir un nuevo rol
Añadir un rol MANAGER que pueda ver los leads pero no eliminarlos.
Ejercicio 2: Token con expiración personalizada
Modificar la duración de validez del token JWT (ej: 1 hora en lugar de 24).
Ejercicio 3: Endpoint con varios roles
Crear un endpoint accesible por ADMIN Y MANAGER.
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")
public List<LeadDto> getLeadsForManagers() {
// ...
}
📖 Acceder a los Cursos
Enlace Directo
📚 Acceder a la carpeta de cursos completa
Consulte los módulos 22 a 28 para una comprensión profunda de la seguridad en Spring Boot.
⏭️ Siguiente Paso
El siguiente capítulo cubre la seguridad de manera aún más detallada con los módulos 11 a 18 de los anexos:
Capítulo 5: Seguridad Avanzada (Módulos 11-18) →