SEC-1396: Implement eager saving of SecurityContext in SessionManagementFilter on authentication.
The user is then seen as being authenticated to further (re-entrant) requests which occur before the existing request has completed. The saving logic is contained with the SecurityContextRepository implementation.
This commit is contained in:
		
							parent
							
								
									403f8da79a
								
							
						
					
					
						commit
						dcbdfc2026
					
				| 
						 | 
				
			
			@ -36,6 +36,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
 | 
			
		|||
import org.springframework.security.config.BeanIds;
 | 
			
		||||
import org.springframework.security.config.PostProcessedMockUserDetailsService;
 | 
			
		||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
 | 
			
		||||
import org.springframework.security.core.context.SecurityContext;
 | 
			
		||||
import org.springframework.security.core.context.SecurityContextHolder;
 | 
			
		||||
import org.springframework.security.core.session.SessionRegistryImpl;
 | 
			
		||||
import org.springframework.security.openid.OpenID4JavaConsumer;
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +78,7 @@ import org.springframework.security.web.authentication.rememberme.TokenBasedReme
 | 
			
		|||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 | 
			
		||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
 | 
			
		||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
 | 
			
		||||
import org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper;
 | 
			
		||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
 | 
			
		||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
 | 
			
		||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
 | 
			
		||||
| 
						 | 
				
			
			@ -790,13 +792,17 @@ public class HttpSecurityBeanDefinitionParserTests {
 | 
			
		|||
        // Register 2 sessions and then check a third
 | 
			
		||||
//        req.setSession(new MockHttpSession());
 | 
			
		||||
//        auth.setDetails(new WebAuthenticationDetails(req));
 | 
			
		||||
        MockHttpServletResponse response = new MockHttpServletResponse();
 | 
			
		||||
        MockHttpServletResponse mockResponse = new MockHttpServletResponse();
 | 
			
		||||
        SaveContextOnUpdateOrErrorResponseWrapper response = new SaveContextOnUpdateOrErrorResponseWrapper(mockResponse, false) {
 | 
			
		||||
            protected void saveContext(SecurityContext context) {
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
 | 
			
		||||
        assertNull(response.getRedirectedUrl());
 | 
			
		||||
        assertNull(mockResponse.getRedirectedUrl());
 | 
			
		||||
        seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
 | 
			
		||||
        assertNull(response.getRedirectedUrl());
 | 
			
		||||
        assertNull(mockResponse.getRedirectedUrl());
 | 
			
		||||
        seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
 | 
			
		||||
        assertEquals("/max-exceeded", response.getRedirectedUrl());
 | 
			
		||||
        assertEquals("/max-exceeded", mockResponse.getRedirectedUrl());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,7 +98,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {
 | 
			
		||||
        SaveToSessionResponseWrapper responseWrapper = (SaveToSessionResponseWrapper)response;
 | 
			
		||||
        SaveContextOnUpdateOrErrorResponseWrapper responseWrapper = (SaveContextOnUpdateOrErrorResponseWrapper)response;
 | 
			
		||||
        // saveContext() might already be called by the response wrapper
 | 
			
		||||
        // if something in the chain called sendError() or sendRedirect(). This ensures we only call it
 | 
			
		||||
        // once per request.
 | 
			
		||||
| 
						 | 
				
			
			@ -289,7 +289,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
 | 
			
		|||
     * Stores the necessary state from the start of the request in order to make a decision about whether
 | 
			
		||||
     * the security context has changed before saving it.
 | 
			
		||||
     */
 | 
			
		||||
    class SaveToSessionResponseWrapper extends SaveContextOnUpdateOrErrorResponseWrapper {
 | 
			
		||||
    final class SaveToSessionResponseWrapper extends SaveContextOnUpdateOrErrorResponseWrapper {
 | 
			
		||||
 | 
			
		||||
        private HttpServletRequest request;
 | 
			
		||||
        private boolean httpSessionExistedAtStartOfRequest;
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +327,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
 | 
			
		|||
         *
 | 
			
		||||
         */
 | 
			
		||||
        @Override
 | 
			
		||||
        void saveContext(SecurityContext context) {
 | 
			
		||||
        protected void saveContext(SecurityContext context) {
 | 
			
		||||
            // See SEC-776
 | 
			
		||||
            if (authenticationTrustResolver.isAnonymous(context.getAuthentication())) {
 | 
			
		||||
                if (logger.isDebugEnabled()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ public abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServ
 | 
			
		|||
     *
 | 
			
		||||
     * @param context the <tt>SecurityContext</tt> instance to store
 | 
			
		||||
     */
 | 
			
		||||
    abstract void saveContext(SecurityContext context);
 | 
			
		||||
    protected abstract void saveContext(SecurityContext context);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Makes sure the session is updated before calling the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,9 @@ public class SessionManagementFilter extends GenericFilterBean {
 | 
			
		|||
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                // Eagerly save the security context to make it available for any possible re-entrant
 | 
			
		||||
                // requests which may occur before the current request completes. SEC-1396.
 | 
			
		||||
                securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response);
 | 
			
		||||
            } else {
 | 
			
		||||
             // No security context or authentication present. Check for a session timeout
 | 
			
		||||
                if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue