Après avoir configuré l'authentification sans état JWT (disponible ici), je voulais comprendre ce qui se passe sous les abstractions de Spring Security en identifiant les composants clés et leurs interactions. Pour rendre cette exploration plus engageante, j'ai réimplémenté une version minimale dans Go en utilisant la bibliothèque HTTP standard. En décomposant trois flux principaux - l'enregistrement, la génération de jetons et l'accès aux ressources protégées - et en les reconstruisant dans Go, j'ai entrepris de mapper les modèles d'authentification de Spring Security à des composants plus simples.
Cet article se concentre spécifiquement sur les flux d'authentification - comment le système vérifie l'identité de l'utilisateur - plutôt que sur l'autorisation. Nous explorerons les flux avec des diagrammes de séquence qui tracent les requêtes à travers différents composants de l'architecture de Spring Security.
Le système fournit trois points de terminaison :
Dans les sections suivantes, j'explique les composants principaux impliqués dans chaque flux, avec un diagramme de séquence pour chacun.
Une demande d'enregistrement contenant un nom d'utilisateur et un mot de passe passe par la chaîne de filtres Spring Security, où un traitement minimal a lieu puisque le point de terminaison d'enregistrement a été configuré pour ne pas nécessiter d'authentification dans SecurityConfiguration. La requête passe ensuite par le DispatcherServlet de Spring, qui l'achemine vers la méthode appropriée dans UserController en fonction du modèle d'URL. La requête atteint le point de terminaison du registre de UserController, où les informations utilisateur sont stockées avec un mot de passe haché.
Une demande de connexion contenant le nom d'utilisateur et le mot de passe passe par la chaîne de filtres Spring Security, où un traitement minimal a lieu car ce point de terminaison est également configuré pour ne pas nécessiter d'authentification dans SecurityConfiguration. La requête passe par le DispatcherServlet de Spring jusqu'au point de terminaison de connexion de UserController, qui délègue à AuthenticationManager. À l'aide des beans configurés définis dans ApplicationConfiguration, AuthenticationManager vérifie les informations d'identification fournies par rapport à celles stockées. Après une authentification réussie, le UserController utilise JwtService pour générer un jeton JWT contenant les informations et les métadonnées de l'utilisateur comme l'heure de création, qui est renvoyé au client pour les demandes authentifiées ultérieures.
Lorsqu'une requête contenant un jeton JWT dans son en-tête Authorization arrive, elle passe par le JwtAuthenticationFilter - un OncePerRequestFilter personnalisé - qui traite le jeton à l'aide de JwtService. S'il est valide, le filtre récupère l'utilisateur via UserDetailsService configuré dans ApplicationConfiguration et définit l'authentification dans SecurityContextHolder. Si le jeton est manquant ou invalide, le filtre permet à la demande de continuer sans définir d'authentification.
Plus tard dans la chaîne, AuthorizationFilter vérifie si la demande est correctement authentifiée via SecurityContextHolder. Lorsqu'il détecte une authentification manquante, il lève une AccessDeniedException. Cette exception est interceptée par ExceptionTranslationFilter, qui vérifie si l'utilisateur est anonyme et délègue au JwtAuthenticationEntryPoint configuré dans SecurityConfiguration pour renvoyer une réponse 401 non autorisée.
Si tous les filtres réussissent, la requête atteint le DispatcherServlet de Spring qui l'achemine vers le point de terminaison getAuthenticatedUser dans UserController. Ce point de terminaison récupère les informations sur l'utilisateur authentifié de SecurityContextHolder qui ont été renseignées pendant le processus de chaîne de filtrage.
Remarque : Spring Security utilise un riche écosystème de filtres et de composants spécialisés pour gérer divers problèmes de sécurité. Pour comprendre le flux d'authentification de base, je me suis concentré uniquement sur les acteurs clés de la validation des jetons JWT et de l'authentification des utilisateurs.
L'implémentation Go fournit des fonctionnalités similaires grâce à une architecture simplifiée qui correspond aux composants clés de Spring Security :
Chaîne de filtres
Répartiteur
Contexte d'authentification
JwtFilter
Filtre d'authentification
JwtService
Les deux implémentations incluent des tests d'intégration (auth_test.go et AuthTest.java) vérifiant les scénarios d'authentification par clé :
Flux d'inscription
Flux de connexion
Accès protégé aux ressources
L'implémentation Java comprend des commentaires détaillés expliquant le déroulement de chaque scénario de test à travers la chaîne de filtres de Spring Security. Ces mêmes flux sont répliqués dans l'implémentation Go à l'aide de composants équivalents.
J'ai examiné l'authentification JWT de Spring Security en la décomposant en flux et en cas de test. Ensuite, j'ai mappé ces modèles aux composants Go. Les tests d'intégration m'ont montré comment les requêtes transitent par la chaîne de filtrage et les composants de Spring Security. Créer des versions simples de ces modèles m'a aidé à comprendre la conception de Spring Security. Les tests ont prouvé que les deux implémentations gèrent l'authentification de la même manière. Grâce à l'analyse, aux tests et à la reconstruction, j'ai acquis une compréhension plus approfondie du fonctionnement de l'authentification de Spring Security.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!