Bonjour ! Dans la leçon précédente, vous avez mis en place un mécanisme de refresh tokens pour offrir une expérience utilisateur fluide tout en maintenant un haut niveau de sécurité. Votre application gère désormais parfaitement l'authentification et le cycle de vie des sessions.
Maintenant que nous savons qui est l'utilisateur (authentification), il est temps de définir ce qu'il a le droit de faire (autorisation). C'est l'objectif de cette leçon : gérer l'autorisation basée sur les rôles avec les annotations @PreAuthorize.
À la fin de cette leçon, vous saurez comment restreindre l'accès à certaines parties de votre API, par exemple en ne rendant un tableau de bord d'administration accessible qu'aux utilisateurs ayant le rôle ADMIN.

1. Fondations : Rôles et Permissions
Avant de coder, clarifions deux concepts fondamentaux : l'authentification et l'autorisation.
SPRING BOOT | SPRING SECURITY 6/7 | Rôles et Permissions
Cette courte introduction de la vidéo de chillotech, que nous utiliserons tout au long de la leçon, pose parfaitement les bases en distinguant l'authentification de l'autorisation, puis en introduisant les rôles et les permissions.
Regardez le segment de 00:14 à 01:51 pour bien vous imprégner de la distinction entre ces concepts clés.
Pour résumer :
- Authentification : Vérifie l'identité de l'utilisateur (login/mot de passe, JWT). C'est ce que nous avons fait jusqu'à présent.
- Autorisation : Vérifie si un utilisateur authentifié a le droit d'effectuer une action ou d'accéder à une ressource. C'est notre sujet du jour.
Dans Spring Security, l'autorisation s'appuie sur les GrantedAuthority. Ce sont les privilèges accordés à l'utilisateur authentifié. Un Role (comme ROLE_ADMIN) est simplement un type de GrantedAuthority. Votre implémentation de UserDetailsServiceImpl est chargée de convertir les rôles stockés en base de données pour votre entité User en une collection de GrantedAuthority.
Une subtilité importante : le préfixe ROLE_
Par défaut, quand vous utilisez l'expression hasRole('ADMIN'), Spring Security cherche en réalité une autorité nommée ROLE_ADMIN. C'est une convention. Si vos rôles en base de données sont stockés sans ce préfixe (par ex. "ADMIN"), vous avez deux options :
- Ajouter manuellement le préfixe dans votre
UserDetailsServiceImpllors de la création desSimpleGrantedAuthority. - Désactiver ce comportement en ajoutant un
Beanà votre configuration de sécurité.
Pour un contrôle total et éviter les surprises, de nombreux développeurs choisissent de désactiver ce préfixe. L'article de tonux-dev explique comment faire cela, dans la section "Nom du rôle Préfixe par défaut", si cela vous intéresse. Pour nos exemples, nous supposerons que le préfixe ROLE_ est géré correctement.
2. Annotation vs Configuration : Deux approches pour l'autorisation
Spring Security propose deux manières principales de configurer les règles d'autorisation :
- Basée sur la configuration (
SecurityFilterChain) : Les règles sont centralisées dans votre classeWebSecurityConfigen chaînant des appels surhttp.authorizeHttpRequests(). C'est utile pour des règles globales. - Basée sur les annotations (
@PreAuthorize) : Les règles sont placées directement sur les méthodes des contrôleurs. C'est idéal pour un contrôle fin et une meilleure lisibilité, car la règle de sécurité est juste à côté du code qu'elle protège.
Compte tenu de votre objectif de maîtriser les architectures propres et les bonnes pratiques, nous allons nous concentrer sur l'approche par annotations, qui est plus modulaire et plus facile à maintenir dans les grands projets.
Pour bien comprendre la première approche avant de nous plonger dans la seconde, regardez comment la vidéo suivante met en place une restriction via la configuration.
SPRING BOOT | SPRING SECURITY 6/7 | Rôles et Permissions
Ce segment montre comment restreindre l'accès à un endpoint GET sur /avis aux rôles ADMINISTRATEUR et MANAGER directement dans la configuration.
Regardez la portion de 31:46 à 35:12. Observez l'utilisation de requestMatchers avec hasRole() et hasAnyRole(). Vous n'avez pas besoin de l'implémenter, comprenez juste le principe pour le comparer à ce qui va suivre.
L'inconvénient de cette méthode est que le fichier de configuration peut vite devenir complexe et difficile à lire si vous avez beaucoup de règles spécifiques.
3. Mise en œuvre avec @PreAuthorize
Passons à la pratique. L'annotation @PreAuthorize nous permet d'utiliser le langage d'expression de Spring (SpEL) pour définir des règles d'accès complexes directement sur nos méthodes de contrôleur.
Étape 1 : Activer la sécurité au niveau des méthodes
Cette fonctionnalité n'est pas activée par défaut. Vous devez l'activer explicitement dans votre configuration de sécurité.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity // <-- AJOUTEZ CETTE ANNOTATION !
public class WebSecurityConfig {
// ... votre configuration existante
}
Dans les versions plus anciennes de Spring Boot (avant la 3), l'annotation était @EnableGlobalMethodSecurity(prePostEnabled = true). L'annotation @EnableMethodSecurity est la version moderne et simplifiée.
Étape 2 : Sécuriser les méthodes du contrôleur
Maintenant que la fonctionnalité est activée, nous pouvons utiliser @PreAuthorize sur n'importe quelle méthode de bean Spring (contrôleurs, services, etc.).
Créons un contrôleur d'exemple pour tester cela :
@RestController
@RequestMapping("/api/boards")
public class BoardController {
@GetMapping("/all")
public String allAccess() {
return "Contenu public.";
}
@GetMapping("/user")
@PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")
public String userAccess() {
return "Contenu pour les utilisateurs connectés.";
}
@GetMapping("/mod")
@PreAuthorize("hasRole('MODERATOR')")
public String moderatorAccess() {
return "Tableau de bord du modérateur.";
}
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return "Tableau de bord de l'administrateur.";
}
}
Ces exemples, inspirés du document [PDF] Authentification (JWT) et gestion des Roles, montrent comment utiliser hasRole() et des opérateurs logiques comme or.
Étape 3 : Démonstration pratique et test
La meilleure façon de comprendre est de le faire. La vidéo suivante vous guide pas à pas pour déplacer la logique de sécurité de la configuration vers les annotations sur un nouveau contrôleur.
SPRING BOOT | SPRING SECURITY 6/7 | Rôles et Permissions
Suivez ce guide pratique pour implémenter l'autorisation par annotation. Le présentateur va refactoriser le code pour créer un UtilisateurController et le sécuriser avec @PreAuthorize.
Visionnez et reproduisez les étapes de 42:03 à 48:44. Ajoutez @EnableMethodSecurity à votre SecurityConfiguration comme montré à 42:44. Créez un nouveau contrôleur ou utilisez-en un existant. Créez une méthode, par exemple pour lister tous les utilisateurs. Ajoutez l'annotation @PreAuthorize("hasRole('ADMIN')") (adaptez le nom du rôle à votre modèle de données, par exemple hasAuthority('ROLE_ADMINISTRATEUR') comme dans la vidéo). Testez avec Postman : a. Connectez-vous en tant qu'utilisateur standard (sans le rôle admin) et tentez d'accéder à l'endpoint. Vous devriez recevoir une erreur 403 Forbidden. b. Connectez-vous en tant qu'administrateur. La requête devrait maintenant réussir et retourner les données.
4. Au-delà des rôles : les permissions granulaires
Parfois, les rôles ne sont pas assez précis. Imaginez que vous ayez des ADMIN qui peuvent lire les données et des SUPER_ADMIN qui peuvent en plus les supprimer. Au lieu de multiplier les rôles, on peut utiliser des permissions (ou autorités).
C'est là que hasAuthority('permission_name') devient plus puissant que hasRole(). Un rôle peut être vu comme un ensemble de permissions.
| Rôle | Permissions |
|---|---|
| USER | READ_ARTICLE, CREATE_COMMENT |
| ADMIN | READ_ARTICLE, CREATE_COMMENT, DELETE_USER |
Avec cette approche, on peut vérifier une permission spécifique : @PreAuthorize("hasAuthority('DELETE_USER')").
La dernière partie de la vidéo de chillotech explique brillamment comment implémenter ce modèle avancé. C'est une excellente pratique qui rend votre système de sécurité beaucoup plus flexible et maintenable.
SPRING BOOT | SPRING SECURITY 6/7 | Rôles et Permissions
Cette partie avancée montre comment créer une énumération de Permissions, les associer à vos rôles, et les utiliser dans @PreAuthorize.
Regardez de 48:44 à 01:05:51. C'est un segment dense, mais conceptuellement très riche. Créez une enum Permission (ex: ADMIN_READ, ADMIN_CREATE, MANAGER_READ). Dans votre enum Role, associez un Set<Permission> à chaque rôle. Modifiez votre User ou UserDetailsImpl pour que getAuthorities() retourne non seulement le rôle (ROLE_ADMIN) mais aussi toutes les permissions associées (ADMIN_READ, ADMIN_CREATE, etc.). Mettez à jour vos annotations pour utiliser les permissions : @PreAuthorize("hasAuthority('ADMINISTRATEUR_READ')").
Même si vous ne l'implémentez pas entièrement maintenant, comprendre cette distinction entre rôle et permission est fondamental pour concevoir des systèmes professionnels et évolutifs.
Conclusion
Félicitations ! Vous maîtrisez désormais un aspect crucial de la sécurité des applications : l'autorisation. En plaçant des règles de sécurité directement là où elles s'appliquent, votre code devient plus lisible, plus sûr et plus facile à faire évoluer.
Points clés à retenir :
- L'autorisation (
@PreAuthorize) complète l'authentification (JWT) en contrôlant ce que les utilisateurs peuvent faire. - L'annotation
@EnableMethodSecurityest indispensable pour activer la sécurité au niveau des méthodes. @PreAuthorizeavec le langage SpEL (hasRole,hasAuthority,or,and) offre un contrôle d'accès puissant et flexible.- L'approche par annotations est souvent préférable à la configuration centralisée pour sa lisibilité et sa modularité.
- Distinguer les rôles des permissions (
hasAuthority) permet de construire des systèmes d'autorisation beaucoup plus granulaires et professionnels.
Dans notre prochaine leçon, nous conclurons les bases de la sécurité en nous assurant que les données les plus sensibles de vos utilisateurs, leurs mots de passe, sont stockées de la manière la plus sûre possible. Nous verrons comment utiliser BCryptPasswordEncoder pour hacher les mots de passe avant de les sauvegarder en base de données.