php editor Zimo is here to answer the question about whether the Spring Security filter obtains session information from Redis. Spring Security is a powerful security framework that provides a complete set of authentication and authorization mechanisms. By default, Spring Security uses HttpSession to manage user session information. However, with configuration, we can store session information in external storage such as Redis. The advantage of this is that it can realize distributed session management and improve the scalability of the system. Therefore, Spring Security filters can obtain session information from Redis.
I am trying to use spring-boot, spring-security and spring-session to implement the login system, and use redis as the storage of the session.
My 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(); } }
My 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); }
and authentication service:
@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); }
If I understand correctly
this.securitycontextholderstrategy.setcontext(context);
Authentication should be kept in the application's memory, e.g. in a threadlocal context
and
`this.securitycontextrepository.savecontext(context, request, response);`
Session information should be saved to redis.
Now when I log in I see the data has been saved to redis:
However, when inspecting what is returned by my login request, I see:
Completely different session id.
My first question is: Why don't these ids match? How does spring know which key to look for?
Another question is: what filter to get data from redis? I try to debug all filters in the filter chain:
[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]
But it seems to read the session information from the httpserletrequest somehow - however, if I remove the key from redis, the authentication fails for the endpoint that requires it.
Did I miss something? Do I retrieve the session information from redis and store it in httpservlerrequest
before my fitler starts? Or how does it read redis data?
thanks for your help.
The value in the session cookie is base64 encoded:
echo '3c048eae-9f73-4df5-a009-bdf802ae37ca' | openssl base64 m2mwndhlywutowy3my00zgy1lwewmdktymrmodayywuzn2nhcg==
echo 'M2MwNDhlYWUtOWY3My00ZGY1LWEwMDktYmRmODAyYWUzN2NhCg==' | openssl base64 -d 3c048eae-9f73-4df5-a009-bdf802ae37ca
So when base64 decoded, the session id of the cookie matches the session id stored in redis.
If you haven't read it yet, I would recommend this document: https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1
Especially the "Understanding Components of Session Management" section: https://www.php.cn/link/e27c71957d1e6c223e0d48a165da2ee1#understanding-session-management-components
You didn't mention which version of spring security you are using, but I'm guessing you are using spring security 6. In this section, there is such a sentence related to sessionauthentication:
The above is the detailed content of Does spring-security filter get session information from redis?. For more information, please follow other related articles on the PHP Chinese website!