I'm really trying to understand how Spring Security works, but I'm a bit lost at the moment. Here's the simple scenario:
- User visits the website home page but doesn't log in
SecurityContextPersistenceFilter
logs that no SecurityContext was available and a new one will be createdAnonymousAuthenticationFilter
populates SecurityContextHolder with an anonymous token- A session is created with ID = C2A35ED5A41E29865FF53162B0024D52
- User lets the page sit idle until the session times out
- User clicks on the About page (or home page again)
SecurityContextPersistenceFilter
again logs that no SecurityContext was available and a new one will be createdAnonymousAuthenticationFilter
again populates SecurityContextHolder with an anonymous tokenSessionManagementFilter
logs that requested session ID C2A35ED5A41E29865FF53162B0024D52 is invalidSessionManagementFilter
logs that it is starting a new session and redirecting to /invalidsession
These pages are configured to .authorizeRequests().antMatchers("/","/home","/about").permitAll().
I have the invalid session option turned on to handle authenticated users: .sessionManagement().invalidSessionUrl("/errors/invalidSession")
. If I comment out that option, then everything described above is exactly the same EXCEPT for step #10 - SessionManagementFilter
sees that the requested session ID is invalid (#9) but does NOT start a new session and perform the redirect (#10).
WHY? What can I do to keep the invalid session option but correctly handle anonymous users, i.e., not be redirected? Or is that just not possible and I'll have to handle authenticated users separately? I'd be very grateful if anyone can help me understand what's happening here and point me in a direction to solve this. Let me know if you need to see my full http configuration.
EDIT
I ran a series of tests with anonymous and registered (authenticated) users. If .sessionManagement().invalidSessionUrl("/errors/invalidSession")
is enabled then both types of users will eventually arrive at the error page. Authenticated users with RememberMe unchecked are the same as anon users. If RememberMe is checked, then the error page appears once RememberMe times out.
If I disable the invalid session option, no users ever get the error page (which makes sense). Both types of users can browse public pages as long as they want and authenticated users will be asked to log in after the session or RememberMe expires.
If you're interested the code involved here is in SessionManagementFilter
if (invalidSessionStrategy != null) {
invalidSessionStrategy
.onInvalidSessionDetected(request, response);
return;
}
If .sessionManagement().invalidSessionUrl
is enabled the default method SimpleRedirectInvalidSessionStrategy
is called, which executes this piece of code:
if (createNewSession) {
request.getSession();
}
redirectStrategy.sendRedirect(request, response, destinationUrl);
The createNewSession
boolean can be set through setCreateNewSession(boolean createNewSession)
, which is described as:
Determines whether a new session should be created before redirecting (to avoid possible looping issues where the same session ID is sent with the redirected request). Alternatively, ensure that the configured URL does not pass through the
SessionManagementFilter
.
So, it looks to me like .sessionManagement().invalidSessionUrl
works best for sites where all pages are authenticated. The options I'm looking at are a custom filter placed before the SessionManagementFilter
that checks the page access and turns 'createNewSession' on/off as needed or turning off the invalid session option and handling it elsewhere for authenticated pages (?). I also stumbled across <%@ page session=“false” %>
in this SO question - Why set a JSP page session = “false” directive? - which I'm going to look into further. Being so new to Spring Security I don't have a good sense of the best practice for handling this situation correctly. Any help would be appreciated.