Explorar o código

Allow redirect strategy to be customized

Closes gh-12795
Mark Chesney hai 1 ano
pai
achega
2638555e53

+ 14 - 2
web/src/main/java/org/springframework/security/web/session/RequestedUrlRedirectInvalidSessionStrategy.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
 
 import org.springframework.security.web.DefaultRedirectStrategy;
 import org.springframework.security.web.RedirectStrategy;
+import org.springframework.util.Assert;
 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
 
 /**
@@ -32,12 +33,13 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
  * detected by the {@code SessionManagementFilter}.
  *
  * @author Craig Andrews
+ * @author Mark Chesney
  */
 public final class RequestedUrlRedirectInvalidSessionStrategy implements InvalidSessionStrategy {
 
 	private final Log logger = LogFactory.getLog(getClass());
 
-	private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
+	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
 
 	private boolean createNewSession = true;
 
@@ -68,4 +70,14 @@ public final class RequestedUrlRedirectInvalidSessionStrategy implements Invalid
 		this.createNewSession = createNewSession;
 	}
 
+	/**
+	 * Sets the redirect strategy to use. The default is {@link DefaultRedirectStrategy}.
+	 * @param redirectStrategy the redirect strategy to use.
+	 * @since 6.2
+	 */
+	public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
+		Assert.notNull(redirectStrategy, "redirectStrategy cannot be null");
+		this.redirectStrategy = redirectStrategy;
+	}
+
 }

+ 37 - 1
web/src/test/java/org/springframework/security/web/session/SessionManagementFilterTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2023 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import jakarta.servlet.FilterChain;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import org.springframework.mock.web.MockFilterChain;
@@ -29,6 +30,7 @@ import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.DefaultRedirectStrategy;
 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
 import org.springframework.security.web.authentication.session.SessionAuthenticationException;
 import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
@@ -46,9 +48,11 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
 /**
  * @author Luke Taylor
  * @author Rob Winch
+ * @author Mark Chesney
  */
 public class SessionManagementFilterTests {
 
+	@BeforeEach
 	@AfterEach
 	public void clearContext() {
 		SecurityContextHolder.clearContext();
@@ -174,6 +178,38 @@ public class SessionManagementFilterTests {
 		assertThat(response.getRedirectedUrl()).isEqualTo("/requested");
 	}
 
+	@Test
+	public void responseIsRedirectedToRequestedUrlIfContextPathIsSetAndSessionIsInvalid() throws Exception {
+		// given
+		DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
+		redirectStrategy.setContextRelative(true);
+		RequestedUrlRedirectInvalidSessionStrategy invalidSessionStrategy = new RequestedUrlRedirectInvalidSessionStrategy();
+		invalidSessionStrategy.setCreateNewSession(true);
+		invalidSessionStrategy.setRedirectStrategy(redirectStrategy);
+		SecurityContextRepository securityContextRepository = mock(SecurityContextRepository.class);
+		SessionAuthenticationStrategy sessionAuthenticationStrategy = mock(SessionAuthenticationStrategy.class);
+		SessionManagementFilter filter = new SessionManagementFilter(securityContextRepository,
+				sessionAuthenticationStrategy);
+		filter.setInvalidSessionStrategy(invalidSessionStrategy);
+		MockHttpServletRequest request = new MockHttpServletRequest();
+		request.setContextPath("/context");
+		request.setRequestedSessionId("xxx");
+		request.setRequestedSessionIdValid(false);
+		request.setRequestURI("/context/requested");
+		MockHttpServletResponse response = new MockHttpServletResponse();
+		FilterChain chain = mock(FilterChain.class);
+
+		// when
+		filter.doFilter(request, response, chain);
+
+		// then
+		verify(securityContextRepository).containsContext(request);
+		verifyNoMoreInteractions(securityContextRepository, sessionAuthenticationStrategy, chain);
+		assertThat(response.isCommitted()).isTrue();
+		assertThat(response.getRedirectedUrl()).isEqualTo("/context/requested");
+		assertThat(response.getStatus()).isEqualTo(302);
+	}
+
 	@Test
 	public void customAuthenticationTrustResolver() throws Exception {
 		AuthenticationTrustResolver trustResolver = mock(AuthenticationTrustResolver.class);