Typically the ExceptionTranslationFilter is what updates the RequestCache when an unauthenticated user accesses a page that requires authentication. This means that public pages are not saved. There is no built in support for remembering the public pages, but it can be done fairly easily by using the RequestCache directly. I have outlined the steps below:
Create a Filter that will save unauthenticated requests in the RequestCache which may look something like this:
Code:
public class UpateSavedRequestFilter extends OncePerRequestFilter {
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
private RequestCache requestCache = new HttpSessionRequestCache();
private RequestMatcher requestMatcher = new AntPathRequestMatcher("/**/*.jsp");
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(requestMatcher.matches(request) && trustResolver.isAnonymous(authentication)) {
requestCache.saveRequest(request, response);
}
filterChain.doFilter(request, response);
}
}
- The point of the RequestMatcher is to ensure that your images, javascript, and css are not saved. Obviously you may need to update this depending on your application.
- There is an instance of RequestMatcher on the HttpSessionRequestMatcher that could be used instead of having an instance on the Filter (assuming you are using HttpSessionRequestFilter)
- You may want to inject the members rather than hard coding (I did this for simplicity)
- The trustResolver ensures that once you are authenticated it does not continue saving the request. This logic could be embedded into a custom RequestMatcher to make it more architecturally sound but for simplicity I just placed in the Filter.
Next insert the custom filter in your security configuration after the FILTER_SECURITY_INTERCEPTOR. As with all of the Spring Security Filter's the order is important. An example configuration is given below.
Code:
<http ...>
...
<custom-filter ref="usrFilter" after="FILTER_SECURITY_INTERCEPTOR"/>
</http>
One thing to keep in mind about this approach is that unauthenticated users will be updating the HttpSession on each page request. This will likely not have a problem, but in a clustered environment where the clusters are synchronizing the Session across the cluster you may need to tune it a bit. If it causes a lot of problems, you can probably just ignore the SPRING_SECURITY_SAVED_REQUEST attribute (i.e. don't replicate it). You will need to refer to your server configuration on how to do this, but for Tomcat you can use the CusterManagement documentation. In the event of a failure, your user will simply go to the default target url (defaults to context root) instead.
I should note that there are other approaches like passing a parameter around on the URLs, but this is risky since it can lead to Unvalidated Redirects.
HTH,