Heim > Java > Erhält der Spring-Security-Filter Sitzungsinformationen von Redis?

Erhält der Spring-Security-Filter Sitzungsinformationen von Redis?

PHPz
Freigeben: 2024-02-09 22:30:08
nach vorne
559 Leute haben es durchsucht

PHP-Editor Zimo ist hier, um die Frage zu beantworten, ob der Spring Security-Filter Sitzungsinformationen von Redis erhält. Spring Security ist ein leistungsstarkes Sicherheitsframework, das einen vollständigen Satz an Authentifizierungs- und Autorisierungsmechanismen bereitstellt. Standardmäßig verwendet Spring Security HttpSession, um Benutzersitzungsinformationen zu verwalten. Mit der Konfiguration können wir jedoch Sitzungsinformationen in einem externen Speicher wie Redis speichern. Dies hat den Vorteil, dass eine verteilte Sitzungsverwaltung realisiert und die Skalierbarkeit des Systems verbessert werden kann. Daher können Spring Security-Filter Sitzungsinformationen von Redis abrufen.

Frageninhalt

Ich versuche, Spring-Boot, Spring-Security und Spring-Session zu verwenden, um das Anmeldesystem zu implementieren, und verwende Redis als Sitzungsspeicher.

Meine Konfiguration:

@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();
    }
}
Nach dem Login kopieren

Mein Login-Controller:

@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);
}
Nach dem Login kopieren

und Authentifizierungsdienst:

@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);
}
Nach dem Login kopieren

Wenn ich das richtig verstehe

this.securitycontextholderstrategy.setcontext(context); Die Authentifizierung sollte im Speicher der Anwendung gespeichert werden, z. B. in einem threadlokalen Kontext

und

`this.securitycontextrepository.savecontext(context, request, response);`
Nach dem Login kopieren

Sitzungsinformationen sollten in Redis gespeichert werden.

Wenn ich mich jetzt anmelde, sehe ich, dass die Daten in Redis gespeichert wurden:

Wenn ich jedoch überprüfe, was meine Anmeldeanfrage zurückgibt, sehe ich Folgendes:

Völlig andere Sitzungs-ID.

Meine erste Frage ist: Warum stimmen diese IDs nicht überein? Woher weiß der Frühling, nach welchem ​​Schlüssel er suchen muss?

Eine andere Frage ist: Welcher Filter, um Daten von Redis zu erhalten? Ich versuche, alle Filter in der Filterkette zu debuggen:

[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]
Nach dem Login kopieren

Aber es scheint irgendwie die Sitzungsinformationen aus der httpserletrequest zu lesen – wenn ich jedoch den Schlüssel aus Redis entferne, schlägt die Authentifizierung für den Endpunkt fehl, der ihn benötigt.

Habe ich etwas verpasst? Rufe ich die Sitzungsinformationen von Redis ab und speichere sie in httpservlerrequest, bevor mein Fitler startet? Oder wie liest es Redis-Daten?

Danke für deine Hilfe.

Workaround

Der Wert im Sitzungscookie ist Base64-codiert:

echo '3c048eae-9f73-4df5-a009-bdf802ae37ca' | openssl base64
m2mwndhlywutowy3my00zgy1lwewmdktymrmodayywuzn2nhcg==
Nach dem Login kopieren
echo 'M2MwNDhlYWUtOWY3My00ZGY1LWEwMDktYmRmODAyYWUzN2NhCg==' | openssl base64 -d
3c048eae-9f73-4df5-a009-bdf802ae37ca
Nach dem Login kopieren

Bei der Base64-Dekodierung stimmt die Sitzungs-ID des Cookies mit der in Redis gespeicherten Sitzungs-ID überein.

Wenn Sie es noch nicht gelesen haben, würde ich dieses Dokument empfehlen: https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1

Besonders der Abschnitt „Die Komponenten des Sitzungsmanagements verstehen“: https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1#understanding-session-management-components

Sie haben nicht erwähnt, welche Version von Spring Security Sie verwenden, aber ich vermute, dass Sie Spring Security 6 verwenden. In diesem Abschnitt gibt es einen solchen Satz im Zusammenhang mit der Sitzungsauthentifizierung:

Das obige ist der detaillierte Inhalt vonErhält der Spring-Security-Filter Sitzungsinformationen von Redis?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage