Allow redirect strategy to be customized

Closes gh-12795
This commit is contained in:
Mark Chesney 2023-09-04 21:15:12 -07:00 committed by Josh Cummings
parent df5b7294db
commit 2638555e53
2 changed files with 51 additions and 3 deletions

View File

@ -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;
}
}

View File

@ -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);