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 ʻAuthenticationProvider
s, 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éfaut
ProviderManager. ʻ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 dans
BasicAuthenticationFilter` 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 LogoutHanlder
s, donc plusieursLogoutHandler
s 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