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

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

PHPz
PHPznach vorne
2024-02-09 22:30:08471Durchsuche

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();
    }
}

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);
}

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);
}

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);`

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]

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==
echo 'M2MwNDhlYWUtOWY3My00ZGY1LWEwMDktYmRmODAyYWUzN2NhCg==' | openssl base64 -d
3c048eae-9f73-4df5-a009-bdf802ae37ca

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen