Aller au contenu principal

Chapitre 1: Introduction à Spring Security

Introduction​

Avant de configurer quoi que ce soit, il est essentiel de comprendre comment Spring Security fonctionne. Ce chapitre pose les fondations qui vous permettront de configurer la sécurité correctement.


🎯 Objectifs du Chapitre​

À la fin de ce chapitre, vous saurez:

  1. ✅ Pourquoi la sécurité est essentielle
  2. ✅ La différence entre Authentication et Authorization
  3. ✅ L'architecture de Spring Security
  4. ✅ Comment fonctionne la chaîne de filtres
  5. ✅ Les concepts clés: Principal, Credentials, Authorities

1. Pourquoi Sécuriser une Application?​

Les Menaces​

Exemples Réels​

AnnéeEntrepriseImpact
2023MOVEit60M+ utilisateurs touchés
2021Facebook533M comptes exposés
2019Capital One100M+ données volées
2017Equifax147M données personnelles

Les 3 Piliers de la Sécurité (CIA)​

┌─────────────────────────────────────────────────┐
│ │
│ C - Confidentialité │
│ Seules les personnes autorisées │
│ peuvent voir les données │
│ │
│ I - Intégrité │
│ Les données ne peuvent pas être │
│ modifiées sans autorisation │
│ │
│ A - Disponibilité │
│ Le système reste accessible │
│ aux utilisateurs légitimes │
│ │
└─────────────────────────────────────────────────┘

2. Authentication vs Authorization​

La Différence Fondamentale​

ConceptQuestionExemple
Authentication"Qui êtes-vous?"Login avec email/mot de passe
Authorization"Avez-vous le droit?"Accéder à /admin (réservé aux admins)

Analogie: Le Club VIP​

En Spring Security​

// Authentication: Qui est connecté?
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); // "jean@example.com"

// Authorization: Quels sont ses droits?
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
// [ROLE_USER] - Pas ROLE_ADMIN!

3. Architecture de Spring Security​

Vue d'Ensemble​

Les Composants Clés​

1. SecurityFilterChain​

La chaîne de filtres qui intercepte TOUTES les requêtes:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}
}

2. AuthenticationManager​

Coordonne l'authentification:

3. UserDetailsService​

Interface pour charger les utilisateurs:

public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

4. PasswordEncoder​

Encode les mots de passe (JAMAIS en clair!):

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

// Utilisation
String encoded = passwordEncoder.encode("monMotDePasse");
// $2a$10$N9qo8uLOickgx2ZMRZoMye...

boolean matches = passwordEncoder.matches("monMotDePasse", encoded);
// true

4. La Chaîne de Filtres en Détail​

Ordre des Filtres (Simplifié)​

1. CorsFilter                    → Gestion CORS
2. CsrfFilter → Protection CSRF
3. LogoutFilter → Gestion déconnexion
4. UsernamePasswordAuthFilter → Login par formulaire
5. BasicAuthenticationFilter → HTTP Basic Auth
6. BearerTokenAuthFilter → JWT/OAuth2
7. AnonymousAuthenticationFilter → Utilisateur anonyme
8. ExceptionTranslationFilter → Gestion des erreurs
9. FilterSecurityInterceptor → Décision d'accès finale

Visualisation du Flow​


5. Concepts Clés​

Principal​

L'identité de l'utilisateur connecté:

@GetMapping("/profile")
public String profile(Principal principal) {
String username = principal.getName();
return "Bienvenue " + username;
}

Authentication Object​

Contient toutes les informations d'authentification:

public interface Authentication {
Collection<? extends GrantedAuthority> getAuthorities(); // Rôles/Permissions
Object getCredentials(); // Mot de passe (souvent effacé après auth)
Object getDetails(); // Détails additionnels (IP, etc.)
Object getPrincipal(); // L'utilisateur (UserDetails)
boolean isAuthenticated();
}

GrantedAuthority​

Représente un rôle ou une permission:

// Rôles (préfixe ROLE_)
new SimpleGrantedAuthority("ROLE_ADMIN");
new SimpleGrantedAuthority("ROLE_USER");

// Permissions
new SimpleGrantedAuthority("READ_USERS");
new SimpleGrantedAuthority("WRITE_USERS");
new SimpleGrantedAuthority("DELETE_USERS");

SecurityContext​

Stocke l'Authentication de l'utilisateur courant:

// Récupérer l'utilisateur connecté
SecurityContext context = SecurityContextHolder.getContext();
Authentication auth = context.getAuthentication();

if (auth != null && auth.isAuthenticated()) {
String username = auth.getName();
// ...
}

UserDetails​

Interface représentant un utilisateur:

public interface UserDetails {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}

6. Types d'Authentification​

1. Form Login (Session)​

Client → POST /login (user, pass)
Server → Set-Cookie: JSESSIONID=xyz
Client → GET /api/data (Cookie: JSESSIONID=xyz)
Server → Vérifie session → 200 OK

Avantages: Simple, géré par le navigateur Inconvénients: Pas adapté aux API REST stateless

2. HTTP Basic​

Client → GET /api/data
Server → 401 + WWW-Authenticate: Basic
Client → GET /api/data (Authorization: Basic base64(user:pass))
Server → 200 OK

Avantages: Simple Inconvénients: Credentials envoyés à chaque requête

3. JWT (Token)​

Client → POST /login (user, pass)
Server → {"token": "eyJhbGciOiJIUzI1..."}
Client → GET /api/data (Authorization: Bearer eyJhbGciOiJIUzI1...)
Server → Vérifie token → 200 OK

Avantages: Stateless, parfait pour API REST Inconvénients: Gestion de l'expiration

4. OAuth2​

Client → Redirect vers Google
Google → Login utilisateur
Google → Redirect avec code
Server → Échange code contre token
Server → Récupère profil utilisateur

Avantages: Pas de mot de passe à gérer, UX moderne Inconvénients: Dépendance externe


7. Configuration Moderne (Spring Security 6+)​

Ancienne Méthode (Déprécié)​

// ❌ NE PLUS UTILISER
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
}
}

Nouvelle Méthode (Spring Security 6+)​

// ✅ UTILISER CETTE APPROCHE
@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.build();
}

@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}

8. Première Configuration​

Dépendance Maven​

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Comportement par Défaut​

Sans aucune configuration, Spring Security:

  • Protège TOUS les endpoints
  • Génère un mot de passe aléatoire (affiché dans les logs)
  • Active le form login sur /login
  • Active le logout sur /logout
Using generated security password: 8e3d7a2c-1234-5678-abcd-ef0123456789

Configuration Minimale​

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/home", "/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
)
.logout(logout -> logout
.permitAll()
)
.build();
}
}

9. Résumé​

Concepts Clés​

ConceptDescription
AuthenticationVérifier l'identité (qui?)
AuthorizationVérifier les droits (quoi?)
SecurityFilterChainChaîne de filtres de sécurité
AuthenticationManagerOrchestre l'authentification
UserDetailsServiceCharge les utilisateurs
PasswordEncoderEncode les mots de passe
SecurityContextStocke l'utilisateur courant

Architecture Simplifiée​

Requête HTTP
↓
SecurityFilterChain (filtres)
↓
AuthenticationManager
↓
UserDetailsService + PasswordEncoder
↓
SecurityContext (stockage)
↓
Application (Controller)

Points Importants​

✅ Spring Security 6+ utilise des @Bean, pas extends WebSecurityConfigurerAdapter
✅ Toujours encoder les mots de passe (BCrypt)
✅ Comprendre Authentication vs Authorization
✅ La sécurité se configure via SecurityFilterChain

🎯 Prochaine Étape​

Maintenant que vous comprenez l'architecture, passons à la pratique avec l'authentification basique.

➡️ Chapitre 2: Authentification Basique


⬅️ Retour au Module 8