Spring Security semble fonctionner pour une raison quelconque, mais je suis accro à sa personnalisation.Je l'ai donc étudié et résumé à partir de l'idée que si vous connaissez l'architecture, vous pourrez la comprendre d'une manière ou d'une autre.
Recherchez quel type de classe joue quel type de rôle selon le scénario d'authentification par formulaire suivant.
La version est confirmée dans 5.2.1.RELEASE.
Comment accéder à l'écran de connexion lorsqu'un utilisateur non authentifié accède à une page nécessitant une authentification. Le flux approximatif est le suivant. Cette fois, je n'expliquerai pas le processus de vérification lors de l'accès, mais il commence à partir de l'endroit où ʻAuthenticationException` est lancée.

ExceptionTranslationFilter
Cause de l'exception qui s'est produite Vérifiez l'exception, et si ʻAuthenticationException est inclus, démarrez le processus d'authentification en utilisant ʻAuthenticationEntryPoint tout en sauvegardant le contenu de la demande dans RequestCache.
RequestCache utilise généralement HttpSession pour stocker le contenu de la demande. HttpSessionRequestCache est utilisé.
Nous verrons à quoi sert RequestCache plus tard.
AuthenticationEntryPoint
Démarrez le processus d'authentification.
Par exemple, LoginUrlAuthenticationEntryPoint redirige vers l'URL de la page de connexion configurée.
BasicAuthenticationEntryPoint renvoie une réponse avec un code d'état de 401 et un en-tête avec WWW-Authenticate pour lancer l'authentification de base.
Il est géré par ʻExceptionTranslationFilter, mais vous n'avez pas besoin d'en être conscient car vous n'avez pas à le personnaliser beaucoup. Il est nécessaire de sélectionner et de définir correctement ʻAuthenticationEntryPoint pour savoir comment démarrer l'authentification.
Par exemple, si vous souhaitez passer à l'écran de connexion, vous devez définir l'URL de l'écran de connexion à l'aide de LoginUrlAuthenticationEntryPoint, et si vous n'avez pas besoin de démarrer le processus d'authentification en supposant que vous serez authentifié à l'avance comme SSO. Par exemple, utilisez Http403ForbiddenEntryPoint.
Il semble que vous puissiez également définir la classe d'implémentation à utiliser pour la requête en utilisant DelegatingAuthenticationEntryPoint.
Tout d'abord, le flux jusqu'à ce que les informations saisies par l'utilisateur soient reçues et que l'authentification soit OK. C'est à peu près comme suit.

AuthenticationManager
ʻAuthenticationManager est en charge de l'authentification. Reçoit un objet ʻAuthentication et renvoie un objet ʻAuthentication si l'authentification est OK. L'argument ʻAuthentication contient uniquement le principal et les informations d'identification requises pour l'authentification, et la valeur de retour ʻAuthentication` contient également des informations telles que les autorités et les détails.
ProviderManager
ʻIl existe ProviderManager comme classe d'implémentation d'AuthenticationManager. Cette classe est utilisée par défaut. Cette classe délègue le processus d'authentification à plusieurs ʻAuthenticationProviders, et si même l'un d'entre eux est OK, l'authentification est réussie.
Ce faisant, il est possible de combiner une pluralité de processus d'authentification tels que l'authentification par formulaire à l'aide d'informations stockées dans une base de données et l'authentification par LDAP.
Vous pouvez également supprimer les informations d'identification de la valeur de retour ʻAuthentication` pour empêcher la persistance des informations sensibles.
AuthenticationProvider
Authentifier. Si la vérification du mot de passe est requise, utilisez cette classe.
Il existe également une méthode pour déterminer s'il s'agit d'une classe d'implémentation authentifiable de ʻAuthentication. Par exemple, dans le cas d'une authentification par formulaire normale, le processus d'authentification peut être effectué s'il existe un nom d'utilisateur et un mot de passe, mais tous les processus d'authentification ne sont pas suffisants. Par conséquent, la méthode supports (Class <?> Authentication)` est utilisée pour déterminer si le processus d'authentification peut être effectué ou non.
Les classes d'implémentation sont fournies pour les méthodes d'authentification générales, vous pouvez donc les utiliser. Cependant, étant donné que la partie qui acquiert les informations utilisateur dépend de la définition de la base de données utilisée par l'application, il existe de nombreux modèles dans lesquels seule cette partie est implémentée.
UserDetailsService
Une interface de traitement de la partie susmentionnée liée à l'acquisition d'informations utilisateur. Il est souvent utilisé en créant une classe d'implémentation pour cette interface et en la définissant sur ʻAuthenticationProvider`.
Les informations à acquérir doivent être une classe qui implémente ʻUserDetails`.
Une classe d'implémentation appelée JdbcDaoImpl est également fournie, mais comme les informations qui peuvent être obtenues sont limitées, je pense que je vais l'implémenter moi-même.
Fondamentalement, il est appelé par Filter. Par exemple, pour effectuer l'authentification par formulaire, ʻUsernamePasswordAuthenticationFilter est appelé. Ce filtre crée un objet ʻUsernamePasswordAuthenticationToken, qui est une classe d'implémentation de ʻAuthenticaion, à partir des informations d'entrée de l'utilisateur, et appelle le processus d'authentification de ʻAuthenticationManager.
Si l'authentification réussit, la tâche consiste à définir les informations d'authentification acquises dans SecurityContextHolder.
(Voir ci-dessous pour SecurityContextHolder)
ʻAuthenticationManagerest peu susceptible d'être implémenté. Il semble que vous devriez utiliser la classe d'implémentation par défautProviderManager. ʻAuthenticationProvider semble fournir la classe d'implémentation souhaitée, alors sélectionnez-la correctement. Cependant, si vous souhaitez créer une nouvelle méthode d'authentification telle que WebAuthn que Spring Security ne prend pas encore en charge, vous devrez l'implémenter. La même chose s'applique à Filter.
Vous créez souvent votre propre classe d'implémentation pour ʻUserDetailsService` pour obtenir des informations sur l'utilisateur.
En rendant persistantes les informations d'authentification obtenues après l'authentification terminée, il devient possible de déterminer si l'authentification a été effectuée ou non, et il est possible d'accéder aux informations de l'utilisateur.

SecurityContext
Un objet qui contient des informations d'identification (ʻAuthentication). Au lieu de conserver les informations d'identification telles quelles, persistez ce SecurityContext`.
SecurityContextRepository
Une interface pour rendre persistant SecurityContext.
Vous pouvez penser à HttpSession comme un endroit pour conserver les informations d'identification, mais Spring Security fournit également HttpSessionSecurityContextRepository, qui est une classe d'implémentation qui utilise HttpSession. (Utilisez-le par défaut)
SecurityContextHolder
La classe qui contient le SecurityContext. Par défaut, il est conservé en utilisant ThreadLocal.
Si vous souhaitez accéder à vos informations d'identification, vous pouvez les récupérer à partir de ce SecurityContextHolder au lieu d'accéder directement à HttpSession.
SecurityContextPersistenceFilter
Récupérez SecurityContext de SecurityContextRepository et définissez-le sur SecurityContextHolder avant le démarrage de tout processus.
Une fois le traitement terminé, récupérez SecurityContext dans SecurityContextHolder, rendez-le persistant en utilisant SecurityContextRepository et supprimez SecurityContext de SecurityContextHolder.
SecurityContextHolder utilise ThreadLocal, mais ce filtre gère le processus de suppression.
Les informations d'identification sont conservées en tant que SecurityContext, et SecurityContextRepository effectue le traitement lié à la persistance, mais vous n'avez pas besoin d'en être très conscient.
Il est bon de se rappeler que vous pouvez obtenir le SecurityContext à partir du SecurityContextHolder.
Certains filtres qui appellent le processus d'authentification peuvent définir le comportement lorsque l'authentification réussit ou échoue.
Par exemple, il peut être défini dans ʻUsernamePasswordAuthenticationFilterqui effectue l'authentification par formulaire, mais pas dansBasicAuthenticationFilter` qui effectue l'authentification de base.
AuthenticationSuccessHandler

Définissez le processus lorsque l'authentification est réussie.
Certaines classes d'implémentation sont fournies, mais «SavedRequestAwareAuthenticationSuccessHandler» est utilisé par défaut.
Cette classe redirige une requête si elle est conservée dans RequestCache.
S'il n'est pas conservé, redirigez vers l'ensemble d'URL par défaut.
Accédez à la page qui requiert une authentification dans l'état non authentifié et soyez redirigé vers l'écran d'authentification. Après cela, lorsque vous avez terminé l'authentification, vous pouvez passer à l'écran que vous tentiez d'afficher en premier car vous utilisez cette classe.
AuthenticationFailureHandler

Définissez le traitement en cas d'échec de l'authentification.
Certaines classes d'implémentation sont également fournies, mais «SimpleUrlAuthenticationFailuerHandler» est utilisé par défaut.
Cette classe est assez simple et redirige vers l'URL spécifiée.
De plus, en stockant l'exception qui s'est produite lorsque l'authentification a échoué dans HttpSession, il est possible de s'y référer à la destination de la redirection.
Utilisez ʻAuthenticationSuccessHandler et ʻAuthenticationFailuerHandler, respectivement, pour définir le comportement après une authentification réussie et infructueuse.
La classe d'implémentation fournie ne redirige que vers l'URL spécifiée (en fonction des paramètres), donc si vous souhaitez effectuer des opérations avancées, vous devez créer une classe d'implémentation.
Veuillez également noter qu'il peut ne pas être possible de définir en fonction de la méthode d'authentification.
Déconnectez-vous également.

LogoutFilter
Après avoir appelé LogoutHandler qui effectue le traitement de déconnexion, appelezLogoutSuccessHandler qui effectue le post-traitement.
Vous pouvez définir une URL pour vous déconnecter. (La valeur par défaut est / logout)
LogoutHandler
Déconnectez-vous du traitement. SecurityContextLogoutHandler rejette HttpSession.
Ou est-ce une prémisse que les informations d'authentification sont stockées dans HttpSession?
Je ne pense pas qu'il soit stocké dans HttpSession en fonction de l'implémentation de SecurityContextRepository. Mais il n'y a pas de méthode pour supprimer. Hum ...
Notez que LogoutFilter utilise une classe appelée CompositeLogoutHandler qui combine plusieurs LogoutHanlders, donc plusieursLogoutHandlers peuvent être exécutés en séquence selon les besoins.
LogoutSuccessHandler
Effectue le traitement une fois la déconnexion terminée. SimpleUrlLogoutSuccessHandler redirige vers l'URL spécifiée.
Si vous souhaitez personnaliser le processus de déconnexion, vous pouvez implémenter LogoutHandler et le définir sur LogoutFilter.
Si vous souhaitez personnaliser la transition d'écran une fois la déconnexion terminée, implémentez LogoutSuccessHandler et définissez-le sur LogoutFilter.
J'ai l'impression de comprendre Spring Security! (A cause de mon esprit)
Recommended Posts