diff --git a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java index e8cbad916d..6b1123ed37 100644 --- a/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/CsrfBeanDefinitionParser.java @@ -183,6 +183,9 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser { BeanDefinitionBuilder csrfAuthenticationStrategy = BeanDefinitionBuilder .rootBeanDefinition(CsrfAuthenticationStrategy.class); csrfAuthenticationStrategy.addConstructorArgReference(this.csrfRepositoryRef); + if (StringUtils.hasText(this.requestHandlerRef)) { + csrfAuthenticationStrategy.addPropertyReference("requestHandler", this.requestHandlerRef); + } return csrfAuthenticationStrategy.getBeanDefinition(); } diff --git a/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java b/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java index 97bffee2f4..c426a92339 100644 --- a/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java @@ -22,6 +22,7 @@ import java.util.List; import jakarta.servlet.Filter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import org.eclipse.jetty.http.HttpStatus; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -336,6 +337,43 @@ public class CsrfConfigTests { // @formatter:on } + @Test + public void postWhenUsingCsrfAndXorCsrfTokenRequestAttributeHandlerThenCsrfAuthenticationStrategyUses() + throws Exception { + this.spring.configLocations(this.xml("WithXorCsrfTokenRequestAttributeHandler"), this.xml("shared-controllers")) + .autowire(); + // @formatter:off + MvcResult mvcResult1 = this.mvc.perform(get("/csrf")) + .andExpect(status().isOk()) + .andReturn(); + // @formatter:on + MockHttpServletRequest request1 = mvcResult1.getRequest(); + MockHttpSession session = (MockHttpSession) request1.getSession(); + CsrfTokenRepository repository = WebTestUtils.getCsrfTokenRepository(request1); + // @formatter:off + MockHttpServletRequestBuilder login = post("/login") + .param("username", "user") + .param("password", "password") + .session(session) + .with(csrf()); + this.mvc.perform(login) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrl("/")); + // @formatter:on + assertThat(repository.loadToken(request1)).isNull(); + // @formatter:off + MvcResult mvcResult2 = this.mvc.perform(get("/csrf").session(session)) + .andExpect(status().isOk()) + .andReturn(); + // @formatter:on + MockHttpServletRequest request2 = mvcResult2.getRequest(); + CsrfToken csrfToken = repository.loadToken(request2); + CsrfToken csrfTokenAttribute = (CsrfToken) request2.getAttribute(CsrfToken.class.getName()); + assertThat(csrfTokenAttribute).isNotNull(); + assertThat(csrfTokenAttribute.getToken()).isNotBlank(); + assertThat(csrfTokenAttribute.getToken()).isNotEqualTo(csrfToken.getToken()); + } + @Test public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication() throws Exception {