Browse Source

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 năm trước cách đây
mục cha
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() {