1
0
mirror of synced 2026-05-22 13:23:17 +00:00

Merge branch '5.8.x'

Closes gh-11894
This commit is contained in:
Rob Winch
2022-09-22 13:47:04 -05:00
30 changed files with 423 additions and 331 deletions
@@ -36,7 +36,7 @@ import org.springframework.security.web.csrf.CsrfAuthenticationStrategy;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfLogoutHandler;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
import org.springframework.security.web.csrf.CsrfTokenRequestResolver;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.csrf.LazyCsrfTokenRepository;
@@ -91,7 +91,7 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
private SessionAuthenticationStrategy sessionAuthenticationStrategy;
private CsrfTokenRequestAttributeHandler requestAttributeHandler;
private CsrfTokenRequestHandler requestHandler;
private CsrfTokenRequestResolver requestResolver;
@@ -131,14 +131,13 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
}
/**
* Specify a {@link CsrfTokenRequestAttributeHandler} to use for making the
* {@code CsrfToken} available as a request attribute.
* @param requestAttributeHandler the {@link CsrfTokenRequestAttributeHandler} to use
* Specify a {@link CsrfTokenRequestHandler} to use for making the {@code CsrfToken}
* available as a request attribute.
* @param requestHandler the {@link CsrfTokenRequestHandler} to use
* @return the {@link CsrfConfigurer} for further customizations
*/
public CsrfConfigurer<H> csrfTokenRequestAttributeHandler(
CsrfTokenRequestAttributeHandler requestAttributeHandler) {
this.requestAttributeHandler = requestAttributeHandler;
public CsrfConfigurer<H> csrfTokenRequestHandler(CsrfTokenRequestHandler requestHandler) {
this.requestHandler = requestHandler;
return this;
}
@@ -247,8 +246,8 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
if (sessionConfigurer != null) {
sessionConfigurer.addSessionAuthenticationStrategy(getSessionAuthenticationStrategy());
}
if (this.requestAttributeHandler != null) {
filter.setRequestAttributeHandler(this.requestAttributeHandler);
if (this.requestHandler != null) {
filter.setRequestHandler(this.requestHandler);
}
if (this.requestResolver != null) {
filter.setRequestResolver(this.requestResolver);
@@ -343,8 +342,8 @@ public final class CsrfConfigurer<H extends HttpSecurityBuilder<H>>
}
CsrfAuthenticationStrategy csrfAuthenticationStrategy = new CsrfAuthenticationStrategy(
this.csrfTokenRepository);
if (this.requestAttributeHandler != null) {
csrfAuthenticationStrategy.setRequestAttributeHandler(this.requestAttributeHandler);
if (this.requestHandler != null) {
csrfAuthenticationStrategy.setRequestHandler(this.requestHandler);
}
return csrfAuthenticationStrategy;
}
@@ -70,7 +70,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
private static final String ATT_REPOSITORY = "token-repository-ref";
private static final String ATT_REQUEST_ATTRIBUTE_HANDLER = "request-attribute-handler-ref";
private static final String ATT_REQUEST_HANDLER = "request-handler-ref";
private static final String ATT_REQUEST_RESOLVER = "request-resolver-ref";
@@ -80,7 +80,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
private String requestMatcherRef;
private String requestAttributeHandlerRef;
private String requestHandlerRef;
private String requestResolverRef;
@@ -102,7 +102,7 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
if (element != null) {
this.csrfRepositoryRef = element.getAttribute(ATT_REPOSITORY);
this.requestMatcherRef = element.getAttribute(ATT_MATCHER);
this.requestAttributeHandlerRef = element.getAttribute(ATT_REQUEST_ATTRIBUTE_HANDLER);
this.requestHandlerRef = element.getAttribute(ATT_REQUEST_HANDLER);
this.requestResolverRef = element.getAttribute(ATT_REQUEST_RESOLVER);
}
if (!StringUtils.hasText(this.csrfRepositoryRef)) {
@@ -119,8 +119,8 @@ public class CsrfBeanDefinitionParser implements BeanDefinitionParser {
if (StringUtils.hasText(this.requestMatcherRef)) {
builder.addPropertyReference("requireCsrfProtectionMatcher", this.requestMatcherRef);
}
if (StringUtils.hasText(this.requestAttributeHandlerRef)) {
builder.addPropertyReference("requestAttributeHandler", this.requestAttributeHandlerRef);
if (StringUtils.hasText(this.requestHandlerRef)) {
builder.addPropertyReference("requestHandler", this.requestHandlerRef);
}
if (StringUtils.hasText(this.requestResolverRef)) {
builder.addPropertyReference("requestResolver", this.requestResolverRef);
@@ -1152,8 +1152,8 @@ csrf-options.attlist &=
## The CsrfTokenRepository to use. The default is HttpSessionCsrfTokenRepository wrapped by LazyCsrfTokenRepository.
attribute token-repository-ref { xsd:token }?
csrf-options.attlist &=
## The CsrfTokenRequestAttributeHandler to use. The default is CsrfTokenRequestProcessor.
attribute request-attribute-handler-ref { xsd:token }?
## The CsrfTokenRequestHandler to use. The default is CsrfTokenRequestProcessor.
attribute request-handler-ref { xsd:token }?
csrf-options.attlist &=
## The CsrfTokenRequestResolver to use. The default is CsrfTokenRequestProcessor.
attribute request-resolver-ref { xsd:token }?
@@ -3256,9 +3256,9 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="request-attribute-handler-ref" type="xs:token">
<xs:attribute name="request-handler-ref" type="xs:token">
<xs:annotation>
<xs:documentation>The CsrfTokenRequestAttributeHandler to use. The default is CsrfTokenRequestProcessor.
<xs:documentation>The CsrfTokenRequestHandler to use. The default is CsrfTokenRequestProcessor.
</xs:documentation>
</xs:annotation>
</xs:attribute>
@@ -1124,8 +1124,8 @@ csrf-options.attlist &=
## The CsrfTokenRepository to use. The default is HttpSessionCsrfTokenRepository wrapped by LazyCsrfTokenRepository.
attribute token-repository-ref { xsd:token }?
csrf-options.attlist &=
## The CsrfTokenRequestAttributeHandler to use. The default is CsrfTokenRequestProcessor.
attribute request-attribute-handler-ref { xsd:token }?
## The CsrfTokenRequestHandler to use. The default is CsrfTokenRequestProcessor.
attribute request-handler-ref { xsd:token }?
csrf-options.attlist &=
## The CsrfTokenRequestResolver to use. The default is CsrfTokenRequestProcessor.
attribute request-resolver-ref { xsd:token }?
@@ -3166,9 +3166,9 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="request-attribute-handler-ref" type="xs:token">
<xs:attribute name="request-handler-ref" type="xs:token">
<xs:annotation>
<xs:documentation>The CsrfTokenRequestAttributeHandler to use. The default is CsrfTokenRequestProcessor.
<xs:documentation>The CsrfTokenRequestHandler to use. The default is CsrfTokenRequestProcessor.
</xs:documentation>
</xs:annotation>
</xs:attribute>
@@ -32,8 +32,8 @@ import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.csrf.LazyCsrfTokenRepository;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.never;
@@ -78,8 +78,7 @@ public class DeferHttpSessionJavaConfigTests {
@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
LazyCsrfTokenRepository csrfRepository = new LazyCsrfTokenRepository(new HttpSessionCsrfTokenRepository());
csrfRepository.setDeferLoadToken(true);
CsrfTokenRepository csrfRepository = new HttpSessionCsrfTokenRepository();
// @formatter:off
http
.authorizeHttpRequests((requests) -> requests
@@ -67,7 +67,6 @@ import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.springframework.security.config.Customizer.withDefaults;
@@ -234,8 +233,6 @@ public class CsrfConfigurerTests {
this.mvc.perform(post("/login").param("username", "user").param("password", "password").with(csrf())
.session((MockHttpSession) mvcResult.getRequest().getSession())).andExpect(status().isFound())
.andExpect(redirectedUrl(redirectUrl));
verify(CsrfDisablesPostRequestFromRequestCacheConfig.REPO, atLeastOnce())
.loadToken(any(HttpServletRequest.class));
}
// SEC-2422
@@ -280,12 +277,12 @@ public class CsrfConfigurerTests {
}
@Test
public void getWhenCustomCsrfTokenRepositoryThenRepositoryIsUsed() throws Exception {
public void postWhenCustomCsrfTokenRepositoryThenRepositoryIsUsed() throws Exception {
CsrfTokenRepositoryConfig.REPO = mock(CsrfTokenRepository.class);
given(CsrfTokenRepositoryConfig.REPO.loadToken(any()))
.willReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token"));
this.spring.register(CsrfTokenRepositoryConfig.class, BasicController.class).autowire();
this.mvc.perform(get("/")).andExpect(status().isOk());
this.mvc.perform(post("/"));
verify(CsrfTokenRepositoryConfig.REPO).loadToken(any(HttpServletRequest.class));
}
@@ -322,7 +319,7 @@ public class CsrfConfigurerTests {
given(CsrfTokenRepositoryInLambdaConfig.REPO.loadToken(any()))
.willReturn(new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token"));
this.spring.register(CsrfTokenRepositoryInLambdaConfig.class, BasicController.class).autowire();
this.mvc.perform(get("/")).andExpect(status().isOk());
this.mvc.perform(post("/"));
verify(CsrfTokenRepositoryInLambdaConfig.REPO).loadToken(any(HttpServletRequest.class));
}
@@ -427,8 +424,8 @@ public class CsrfConfigurerTests {
CsrfTokenRepository csrfTokenRepository = mock(CsrfTokenRepository.class);
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
given(csrfTokenRepository.generateToken(any(HttpServletRequest.class))).willReturn(csrfToken);
CsrfTokenRequestProcessorConfig.REPO = csrfTokenRepository;
CsrfTokenRequestProcessorConfig.PROCESSOR = new CsrfTokenRequestProcessor();
CsrfTokenRequestProcessorConfig.PROCESSOR.setTokenRepository(csrfTokenRepository);
this.spring.register(CsrfTokenRequestProcessorConfig.class, BasicController.class).autowire();
this.mvc.perform(get("/login")).andExpect(status().isOk())
.andExpect(content().string(containsString(csrfToken.getToken())));
@@ -443,10 +440,11 @@ public class CsrfConfigurerTests {
public void loginWhenCsrfTokenRequestProcessorSetAndNormalCsrfTokenThenSuccess() throws Exception {
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token");
CsrfTokenRepository csrfTokenRepository = mock(CsrfTokenRepository.class);
given(csrfTokenRepository.loadToken(any(HttpServletRequest.class))).willReturn(csrfToken);
given(csrfTokenRepository.loadToken(any(HttpServletRequest.class))).willReturn(null, csrfToken);
given(csrfTokenRepository.generateToken(any(HttpServletRequest.class))).willReturn(csrfToken);
CsrfTokenRequestProcessorConfig.REPO = csrfTokenRepository;
CsrfTokenRequestProcessorConfig.PROCESSOR = new CsrfTokenRequestProcessor();
CsrfTokenRequestProcessorConfig.PROCESSOR.setTokenRepository(csrfTokenRepository);
this.spring.register(CsrfTokenRequestProcessorConfig.class, BasicController.class).autowire();
// @formatter:off
MockHttpServletRequestBuilder loginRequest = post("/login")
@@ -455,8 +453,7 @@ public class CsrfConfigurerTests {
.param("password", "password");
// @formatter:on
this.mvc.perform(loginRequest).andExpect(redirectedUrl("/"));
verify(csrfTokenRepository, times(2)).loadToken(any(HttpServletRequest.class));
verify(csrfTokenRepository).saveToken(isNull(), any(HttpServletRequest.class), any(HttpServletResponse.class));
verify(csrfTokenRepository).loadToken(any(HttpServletRequest.class));
verify(csrfTokenRepository).generateToken(any(HttpServletRequest.class));
verify(csrfTokenRepository).saveToken(eq(csrfToken), any(HttpServletRequest.class),
any(HttpServletResponse.class));
@@ -826,8 +823,6 @@ public class CsrfConfigurerTests {
@EnableWebSecurity
static class CsrfTokenRequestProcessorConfig {
static CsrfTokenRepository REPO;
static CsrfTokenRequestProcessor PROCESSOR;
@Bean
@@ -839,8 +834,7 @@ public class CsrfConfigurerTests {
)
.formLogin(Customizer.withDefaults())
.csrf((csrf) -> csrf
.csrfTokenRepository(REPO)
.csrfTokenRequestAttributeHandler(PROCESSOR)
.csrfTokenRequestHandler(PROCESSOR)
.csrfTokenRequestResolver(PROCESSOR)
);
// @formatter:on
@@ -29,6 +29,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.test.SpringTestContext;
@@ -41,6 +42,7 @@ import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.DeferredCsrfToken;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -544,8 +546,9 @@ public class CsrfConfigTests {
@Override
public void match(MvcResult result) {
MockHttpServletRequest request = result.getRequest();
CsrfToken token = WebTestUtils.getCsrfTokenRepository(request).loadToken(request);
assertThat(token).isNotNull();
MockHttpServletResponse response = result.getResponse();
DeferredCsrfToken token = WebTestUtils.getCsrfTokenRequestHandler(request).handle(request, response);
assertThat(token.isGenerated()).isFalse();
}
}
@@ -561,7 +564,8 @@ public class CsrfConfigTests {
@Override
public void match(MvcResult result) throws Exception {
MockHttpServletRequest request = result.getRequest();
CsrfToken token = WebTestUtils.getCsrfTokenRepository(request).loadToken(request);
MockHttpServletResponse response = result.getResponse();
CsrfToken token = WebTestUtils.getCsrfTokenRequestHandler(request).handle(request, response).get();
assertThat(token).isNotNull();
assertThat(token.getToken()).isEqualTo(this.token.apply(result));
}
@@ -41,7 +41,6 @@ import org.springframework.security.web.csrf.DefaultCsrfToken
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.get
import org.springframework.test.web.servlet.post
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RestController
@@ -125,9 +124,9 @@ class CsrfDslTests {
CustomRepositoryConfig.REPO.loadToken(any())
} returns DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "token")
this.mockMvc.get("/test1")
this.mockMvc.post("/test1")
verify(exactly = 1) { CustomRepositoryConfig.REPO.loadToken(any()) }
verify(exactly = 1) { CustomRepositoryConfig.REPO.loadToken(any()) }
}
@Configuration
@@ -23,10 +23,10 @@
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<csrf request-attribute-handler-ref="requestAttributeHandler"/>
<csrf request-handler-ref="requestHandler"/>
</http>
<b:bean id="requestAttributeHandler" class="org.springframework.security.web.csrf.CsrfTokenRequestProcessor"
<b:bean id="requestHandler" class="org.springframework.security.web.csrf.CsrfTokenRequestProcessor"
p:csrfRequestAttributeName="csrf-attribute-name"/>
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
</b:beans>
@@ -40,5 +40,7 @@
<b:bean id="csrfRepository" class="org.springframework.security.web.csrf.LazyCsrfTokenRepository"
c:delegate-ref="httpSessionCsrfRepository"
p:deferLoadToken="true"/>
<b:bean id="requestHandler" class="org.springframework.security.web.csrf.CsrfTokenRequestProcessor"
p:csrfRequestAttributeName="_csrf"/>
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
</b:beans>