Maison > Java > Le filtre de sécurité Spring obtient-il des informations de session de Redis ?

Le filtre de sécurité Spring obtient-il des informations de session de Redis ?

PHPz
Libérer: 2024-02-09 22:30:08
avant
537 Les gens l'ont consulté

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.

Contenu de la question

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();
    }
}
Copier après la connexion

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);
}
Copier après la connexion

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);
}
Copier après la connexion

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);`
Copier après la connexion

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]
Copier après la connexion

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.

Solution

La valeur dans le cookie de session est codée en base64 :

echo '3c048eae-9f73-4df5-a009-bdf802ae37ca' | openssl base64
m2mwndhlywutowy3my00zgy1lwewmdktymrmodayywuzn2nhcg==
Copier après la connexion
echo 'M2MwNDhlYWUtOWY3My00ZGY1LWEwMDktYmRmODAyYWUzN2NhCg==' | openssl base64 -d
3c048eae-9f73-4df5-a009-bdf802ae37ca
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal