L'éditeur PHP Zimo est là pour répondre à la question de savoir si le filtre Spring Security obtient les informations de session de Redis. Spring Security est un cadre de sécurité puissant qui fournit un ensemble complet de mécanismes d'authentification et d'autorisation. Par défaut, Spring Security utilise HttpSession pour gérer les informations de session utilisateur. Cependant, avec la configuration, nous pouvons stocker les informations de session dans un stockage externe tel que Redis. L'avantage est qu'il peut réaliser une gestion de session distribuée et améliorer l'évolutivité du système. Par conséquent, les filtres Spring Security peuvent obtenir des informations de session auprès de Redis.
J'essaie d'utiliser spring-boot, spring-security et spring-session pour implémenter le système de connexion et d'utiliser redis comme stockage de la session.
Ma configuration :
@enablewebsecurity @enablemethodsecurity @configuration @requiredargsconstructor public class securityconfig { private final userdetailsservice detailsservice; @bean public passwordencoder passwordencoder() { return new bcryptpasswordencoder(); } @bean public authenticationprovider authenticationprovider(passwordencoder passwordencoder) { daoauthenticationprovider provider = new daoauthenticationprovider(); provider.setpasswordencoder(passwordencoder); provider.setuserdetailsservice(this.detailsservice); return provider; } @bean public authenticationmanager authenticationmanager(authenticationprovider authenticationprovider) { return new providermanager(authenticationprovider); } @bean public securityfilterchain filterchain(httpsecurity http) throws exception { return http .csrf().disable() .cors(customizer.withdefaults()) .authorizehttprequests(auth -> { auth.requestmatchers("/api/v1/auth/register/**", "/api/v1/auth/login").permitall(); auth.anyrequest().authenticated(); }) .sessionmanagement(sessionmanagement -> sessionmanagement .sessioncreationpolicy(if_required) // .sessionfixation(sessionmanagementconfigurer.sessionfixationconfigurer::newsession) // .maximumsessions(100000) // //.sessionregistry(sessionregistry()) ) //.exceptionhandling((ex) -> ex.authenticationentrypoint(this.authentrypoint)) .logout(out -> out .logouturl("/api/v1/auth/logout") .invalidatehttpsession(true) // invalidate all sessions after logout .deletecookies("jsessionid") .logoutsuccesshandler((request, response, authentication) -> securitycontextholder.clearcontext() ) ) .build(); } @bean public securitycontextrepository securitycontextrepository() { return new httpsessionsecuritycontextrepository(); } }
Mon contrôleur de connexion :
@postmapping("/login") public void login(@requestbody loginform form, httpservletrequest request, httpservletresponse response) { string ip = httprequestutil.getip(request); string device = httprequestutil.getdevice(request); loginformwrapper loginformwrapper = new loginformwrapper(form.email(), form.password(), ip, device); authenticationservice.login(loginformwrapper, request, response); }
et service d'authentification :
@override public void login(loginformwrapper form, httpservletrequest request, httpservletresponse response) { authentication authentication = authenticationmanager.authenticate(usernamepasswordauthenticationtoken.unauthenticated( form.email().trim(), form.password())); // create a new context securitycontext context = securitycontextholder.createemptycontext(); context.setauthentication(authentication); // update securitycontextholder and strategy this.securitycontextholderstrategy.setcontext(context); this.securitycontextrepository.savecontext(context, request, response); }
Si j'ai bien compris
this.securitycontextholderstrategy.setcontext(context);
L'authentification doit être conservée dans la mémoire de l'application, par exemple dans un contexte threadlocal
et
`this.securitycontextrepository.savecontext(context, request, response);`
Les informations de session doivent être enregistrées sur Redis.
Maintenant, lorsque je me connecte, je vois que les données ont été enregistrées sur Redis :
Cependant, en vérifiant ce qui est retourné par ma demande de connexion, je vois :
Identifiant de session complètement différent.
Ma première question est : Pourquoi ces identifiants ne correspondent-ils pas ? Comment Spring sait-il quelle clé rechercher ?
Une autre question est : quel filtre pour obtenir les données de Redis ? J'essaie de déboguer tous les filtres de la chaîne de filtres :
[org.springframework.security.web.session.DisableEncodeUrlFilter@2fedae96, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@4945cd1f, org.springframework.security.web.context.SecurityContextHolderFilter@72499396, org.springframework.security.web.header.HeaderWriterFilter@7048d039, org.springframework.web.filter.CorsFilter@2dbfcbe4, org.springframework.security.web.authentication.logout.LogoutFilter@5d5a77de, org.springframework.security.web.session.ConcurrentSessionFilter@1f8e1096, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@651bec9a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@76d4e1af, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6f13ed1, org.springframework.security.web.session.SessionManagementFilter@642693c2, org.springframework.security.web.access.ExceptionTranslationFilter@2199e1a4, org.springframework.security.web.access.intercept.AuthorizationFilter@48c584c]
Mais il semble lire les informations de session à partir de httpserletrequest d'une manière ou d'une autre - cependant, si je supprime la clé de Redis, l'authentification du point de terminaison qui l'exige échoue.
Est-ce que j'ai raté quelque chose ? Dois-je récupérer les informations de session de Redis et les stocker dans httpservlerrequest
avant le démarrage de mon fitler ? Ou comment lit-il les données Redis ?
Merci pour votre aide.
La valeur dans le cookie de session est codée en base64 :
echo '3c048eae-9f73-4df5-a009-bdf802ae37ca' | openssl base64 m2mwndhlywutowy3my00zgy1lwewmdktymrmodayywuzn2nhcg==
echo 'M2MwNDhlYWUtOWY3My00ZGY1LWEwMDktYmRmODAyYWUzN2NhCg==' | openssl base64 -d 3c048eae-9f73-4df5-a009-bdf802ae37ca
Ainsi, lors du décodage en base64, l'identifiant de session du cookie correspond à l'identifiant de session stocké dans Redis.
Si vous ne l'avez pas encore lu, je vous recommande ce document : https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1
Surtout la section « Comprendre les composants de la gestion de session » : https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1#understanding-session-management-components
Vous n'avez pas mentionné la version de Spring Security que vous utilisez, mais je suppose que vous utilisez Spring Security 6. Dans cette section, il y a une phrase liée à l'authentification de session :
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!