2
0
Эх сурвалжийг харах

SEC-1142: Support for session timeout detection. Added redirect to invalidSessionUrl in SessionManagementFilter when an invalid session Id is supplied in the request.

Luke Taylor 16 жил өмнө
parent
commit
90d76373cc

+ 17 - 0
web/src/main/java/org/springframework/security/web/session/SessionManagementFilter.java

@@ -40,6 +40,8 @@ public class SessionManagementFilter extends SpringSecurityFilter {
 
     private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
 
+    private String invalidSessionUrl;
+
     public SessionManagementFilter(SecurityContextRepository securityContextRepository) {
         this.securityContextRepository = securityContextRepository;
     }
@@ -60,12 +62,23 @@ public class SessionManagementFilter extends SpringSecurityFilter {
             if (authentication != null && !authenticationTrustResolver.isAnonymous(authentication)) {
              // The user has been authenticated during the current request, so call the session strategy
                 sessionStrategy.onAuthenticationSuccess(authentication, request, response);
+            } else {
+             // No security context or authentication present. Check for a session timeout
+                if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
+                    invalidSessionRequested(request, response);
+                }
             }
         }
 
         chain.doFilter(request, response);
     }
 
+    protected void invalidSessionRequested(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        if (invalidSessionUrl != null) {
+            response.sendRedirect(invalidSessionUrl);
+        }
+    }
+
     /**
      * Sets the strategy object which handles the session management behaviour when a
      * user has been authenticated during the current request.
@@ -76,4 +89,8 @@ public class SessionManagementFilter extends SpringSecurityFilter {
         Assert.notNull(sessionStrategy, "authenticatedSessionStratedy must not be null");
         this.sessionStrategy = sessionStrategy;
     }
+
+    public void setInvalidSessionUrl(String sessionTimeoutUrl) {
+        this.invalidSessionUrl = sessionTimeoutUrl;
+    }
 }

+ 27 - 0
web/src/test/java/org/springframework/security/web/session/SessionManagementFilterTests.java

@@ -83,6 +83,33 @@ public class SessionManagementFilterTests {
         filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
 
         verify(strategy).onAuthenticationSuccess(any(Authentication.class), any(HttpServletRequest.class), any(HttpServletResponse.class));
+        // Check that it is only applied once to the request
+        filter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
+        verifyNoMoreInteractions(strategy);
+    }
+
+    @Test
+    public void responseIsRedirectedToTimeoutUrlIfSetAndSessionIsInvalid() throws Exception {
+        SecurityContextRepository repo = mock(SecurityContextRepository.class);
+        // repo will return false to containsContext()
+        AuthenticatedSessionStrategy strategy = mock(AuthenticatedSessionStrategy.class);
+        SessionManagementFilter filter = new SessionManagementFilter(repo);
+        filter.setAuthenticatedSessionStrategy(strategy);
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        request.setRequestedSessionId("xxx");
+        request.setRequestedSessionIdValid(false);
+        MockHttpServletResponse response = new MockHttpServletResponse();
+
+        filter.doFilter(request, response, new MockFilterChain());
+        assertNull(response.getRedirectedUrl());
+
+        // Now set a redirect URL
+        request = new MockHttpServletRequest();
+        request.setRequestedSessionId("xxx");
+        request.setRequestedSessionIdValid(false);
+        filter.setInvalidSessionUrl("/timedOut");
+        filter.doFilter(request, response, new MockFilterChain());
+        assertEquals("/timedOut", response.getRedirectedUrl());
     }
 
     private void authenticateUser() {