2
0
Эх сурвалжийг харах

CsrfConfigTests groovy->java

Issue: gh-4939
Josh Cummings 7 жил өмнө
parent
commit
3c1231efd3
14 өөрчлөгдсөн 985 нэмэгдсэн , 342 устгасан
  1. 0 342
      config/src/test/groovy/org/springframework/security/config/http/CsrfConfigTests.groovy
  2. 646 0
      config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java
  3. 27 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-AutoConfig.xml
  4. 29 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfDisabled.xml
  5. 30 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml
  6. 30 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-WithAccessDeniedHandler.xml
  7. 29 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-WithRequestMatcher.xml
  8. 30 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-WithSessionManagement.xml
  9. 28 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-mock-csrf-token-repository.xml
  10. 27 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-mock-request-matcher.xml
  11. 25 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-access-denied-handler.xml
  12. 33 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-controllers.xml
  13. 25 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-csrf-token-repository.xml
  14. 26 0
      config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-userservice.xml

+ 0 - 342
config/src/test/groovy/org/springframework/security/config/http/CsrfConfigTests.groovy

@@ -1,342 +0,0 @@
-/*
- * Copyright 2002-2012 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. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
-package org.springframework.security.config.http
-
-import javax.servlet.http.HttpServletRequest
-import javax.servlet.http.HttpServletResponse
-
-import spock.lang.Unroll
-
-import org.springframework.mock.web.MockFilterChain
-import org.springframework.mock.web.MockHttpServletRequest
-import org.springframework.mock.web.MockHttpServletResponse
-import org.springframework.security.access.AccessDeniedException
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
-import org.springframework.security.core.Authentication
-import org.springframework.security.core.authority.AuthorityUtils
-import org.springframework.security.core.context.SecurityContextImpl
-import org.springframework.security.web.access.AccessDeniedHandler
-import org.springframework.security.web.context.HttpRequestResponseHolder
-import org.springframework.security.web.context.HttpSessionSecurityContextRepository
-import org.springframework.security.web.csrf.CsrfFilter
-import org.springframework.security.web.csrf.CsrfToken
-import org.springframework.security.web.csrf.CsrfTokenRepository
-import org.springframework.security.web.csrf.DefaultCsrfToken
-import org.springframework.security.web.util.matcher.RequestMatcher
-import org.springframework.web.servlet.support.RequestDataValueProcessor
-
-import static org.mockito.Matchers.*
-import static org.mockito.Mockito.*
-
-/**
- *
- * @author Rob Winch
- */
-class CsrfConfigTests extends AbstractHttpConfigTests {
-	MockHttpServletRequest request = new MockHttpServletRequest()
-	MockHttpServletResponse response = new MockHttpServletResponse()
-	MockFilterChain chain = new MockFilterChain()
-
-	@Unroll
-	def 'csrf is enabled by default'() {
-		setup:
-		httpAutoConfig {
-		}
-		createAppContext()
-		when:
-		request.method = httpMethod
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == httpStatus
-		where:
-		httpMethod | httpStatus
-		'POST'	   | HttpServletResponse.SC_FORBIDDEN
-		'PUT'	   | HttpServletResponse.SC_FORBIDDEN
-		'PATCH'	   | HttpServletResponse.SC_FORBIDDEN
-		'DELETE'   | HttpServletResponse.SC_FORBIDDEN
-		'INVALID'  | HttpServletResponse.SC_FORBIDDEN
-		'GET'	   | HttpServletResponse.SC_OK
-		'HEAD'	   | HttpServletResponse.SC_OK
-		'TRACE'	   | HttpServletResponse.SC_OK
-		'OPTIONS'  | HttpServletResponse.SC_OK
-	}
-
-	def 'csrf disabled'() {
-		when:
-		httpAutoConfig { csrf(disabled:true) }
-		createAppContext()
-		then:
-		!getFilter(CsrfFilter)
-	}
-
-	@Unroll
-	def 'csrf defaults'() {
-		setup:
-		httpAutoConfig { 'csrf'() }
-		createAppContext()
-		when:
-		request.method = httpMethod
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == httpStatus
-		where:
-		httpMethod | httpStatus
-		'POST'	   | HttpServletResponse.SC_FORBIDDEN
-		'PUT'	   | HttpServletResponse.SC_FORBIDDEN
-		'PATCH'	   | HttpServletResponse.SC_FORBIDDEN
-		'DELETE'   | HttpServletResponse.SC_FORBIDDEN
-		'INVALID'  | HttpServletResponse.SC_FORBIDDEN
-		'GET'	   | HttpServletResponse.SC_OK
-		'HEAD'	   | HttpServletResponse.SC_OK
-		'TRACE'	   | HttpServletResponse.SC_OK
-		'OPTIONS'  | HttpServletResponse.SC_OK
-	}
-
-	def 'csrf default creates CsrfRequestDataValueProcessor'() {
-		when:
-		httpAutoConfig { 'csrf'() }
-		createAppContext()
-		then:
-		appContext.getBean("requestDataValueProcessor",RequestDataValueProcessor)
-	}
-
-	def 'csrf custom AccessDeniedHandler'() {
-		setup:
-		httpAutoConfig {
-			'access-denied-handler'(ref:'adh')
-			'csrf'()
-		}
-		mockBean(AccessDeniedHandler,'adh')
-		createAppContext()
-		AccessDeniedHandler adh = appContext.getBean(AccessDeniedHandler)
-		request.method = "POST"
-		when:
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		verify(adh).handle(any(HttpServletRequest),any(HttpServletResponse),any(AccessDeniedException))
-		response.status == HttpServletResponse.SC_OK // our mock doesn't do anything
-	}
-
-	def "csrf disables posts for RequestCache"() {
-		setup:
-		httpAutoConfig {
-			'csrf'('token-repository-ref':'repo')
-			'intercept-url'(pattern:"/**",access:'ROLE_USER')
-		}
-		mockBean(CsrfTokenRepository,'repo')
-		createAppContext()
-		CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-		CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-		when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-		when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
-		request.setParameter(token.parameterName,token.token)
-		request.servletPath = "/some-url"
-		request.requestURI = "/some-url"
-		request.method = "POST"
-		when: "CSRF passes and our session times out"
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: "sent to the login page"
-		response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-		response.redirectedUrl == "http://localhost/login"
-		when: "authenticate successfully"
-		response = new MockHttpServletResponse()
-		request = new MockHttpServletRequest(session: request.session)
-		request.servletPath = "/login"
-		request.setParameter(token.parameterName,token.token)
-		request.setParameter("username","user")
-		request.setParameter("password","password")
-		request.method = "POST"
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: "sent to default success because we don't want csrf attempts made prior to authentication to pass"
-		response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-		response.redirectedUrl == "/"
-	}
-
-	def "csrf enables gets for RequestCache"() {
-		setup:
-		httpAutoConfig {
-			'csrf'('token-repository-ref':'repo')
-			'intercept-url'(pattern:"/**",access:'ROLE_USER')
-		}
-		mockBean(CsrfTokenRepository,'repo')
-		createAppContext()
-		CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-		CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-		when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-		when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
-		request.setParameter(token.parameterName,token.token)
-		request.servletPath = "/some-url"
-		request.requestURI = "/some-url"
-		request.method = "GET"
-		when: "CSRF passes and our session times out"
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: "sent to the login page"
-		response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-		response.redirectedUrl == "http://localhost/login"
-		when: "authenticate successfully"
-		response = new MockHttpServletResponse()
-		request = new MockHttpServletRequest(session: request.session)
-		request.servletPath = "/login"
-		request.setParameter(token.parameterName,token.token)
-		request.setParameter("username","user")
-		request.setParameter("password","password")
-		request.method = "POST"
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: "sent to original URL since it was a GET"
-		response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-		response.redirectedUrl == "http://localhost/some-url"
-	}
-
-	def "SEC-2422: csrf expire CSRF token and session-management invalid-session-url"() {
-		setup:
-		httpAutoConfig {
-			'csrf'()
-			'session-management'('invalid-session-url': '/error/sessionError')
-		}
-		createAppContext()
-		request.setParameter("_csrf","abc")
-		request.method = "POST"
-		when: "No existing expected CsrfToken (session times out) and a POST"
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: "sent to the session timeout page page"
-		response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-		response.redirectedUrl == "/error/sessionError"
-		when: "Existing expected CsrfToken and a POST (invalid token provided)"
-		response = new MockHttpServletResponse()
-		request = new MockHttpServletRequest(session: request.session, method:'POST')
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: "Access Denied occurs"
-		response.status == HttpServletResponse.SC_FORBIDDEN
-	}
-
-	def "csrf requireCsrfProtectionMatcher"() {
-		setup:
-		httpAutoConfig { 'csrf'('request-matcher-ref':'matcher') }
-		mockBean(RequestMatcher,'matcher')
-		createAppContext()
-		request.method = 'POST'
-		RequestMatcher matcher = appContext.getBean("matcher",RequestMatcher)
-		when:
-		when(matcher.matches(any(HttpServletRequest))).thenReturn(false)
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == HttpServletResponse.SC_OK
-		when:
-		when(matcher.matches(any(HttpServletRequest))).thenReturn(true)
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == HttpServletResponse.SC_FORBIDDEN
-	}
-
-	def "csrf csrfTokenRepository default delays save"() {
-		setup:
-		httpAutoConfig {
-		}
-		createAppContext()
-		request.method = "GET"
-		when:
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == HttpServletResponse.SC_OK
-		request.getSession(false) == null
-	}
-
-	def "csrf csrfTokenRepository"() {
-		setup:
-		httpAutoConfig { 'csrf'('token-repository-ref':'repo') }
-		mockBean(CsrfTokenRepository,'repo')
-		createAppContext()
-		CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-		CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-		when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-		request.setParameter(token.parameterName,token.token)
-		request.method = "POST"
-		when:
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == HttpServletResponse.SC_OK
-		when:
-		request.setParameter(token.parameterName,token.token+"INVALID")
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		response.status == HttpServletResponse.SC_FORBIDDEN
-	}
-
-	def "csrf clears on login"() {
-		setup:
-		httpAutoConfig { 'csrf'('token-repository-ref':'repo') }
-		mockBean(CsrfTokenRepository,'repo')
-		createAppContext()
-		CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-		CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-		when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-		when(repo.generateToken(any(HttpServletRequest))).thenReturn(token)
-		request.setParameter(token.parameterName,token.token)
-		request.method = "POST"
-		request.setParameter("username","user")
-		request.setParameter("password","password")
-		request.servletPath = "/login"
-		when:
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		verify(repo, atLeastOnce()).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
-	}
-
-	def "csrf clears on logout"() {
-		setup:
-		httpAutoConfig { 'csrf'('token-repository-ref':'repo') }
-		mockBean(CsrfTokenRepository,'repo')
-		createAppContext()
-		CsrfTokenRepository repo = appContext.getBean("repo",CsrfTokenRepository)
-		CsrfToken token = new DefaultCsrfToken("X-CSRF-TOKEN","_csrf", "abc")
-		when(repo.loadToken(any(HttpServletRequest))).thenReturn(token)
-		request.setParameter(token.parameterName,token.token)
-		request.method = "POST"
-		request.servletPath = "/logout"
-		when:
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		verify(repo).saveToken(eq(null),any(HttpServletRequest), any(HttpServletResponse))
-	}
-
-	def "SEC-2495: csrf disables logout on GET"() {
-		setup:
-		httpAutoConfig { 'csrf'() }
-		createAppContext()
-		login()
-		request.method = "GET"
-		request.requestURI = "/logout"
-		when:
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then:
-		getAuthentication(request) != null
-	}
-
-
-	def login(String username="user", String role="ROLE_USER") {
-		login(new UsernamePasswordAuthenticationToken(username, null, AuthorityUtils.createAuthorityList(role)))
-	}
-
-	def login(Authentication auth) {
-		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-		repo.loadContext(requestResponseHolder)
-		repo.saveContext(new SecurityContextImpl(authentication:auth), requestResponseHolder.request, requestResponseHolder.response)
-	}
-
-	def getAuthentication(HttpServletRequest request) {
-		HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository()
-		HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response)
-		repo.loadContext(requestResponseHolder)?.authentication
-	}
-}

+ 646 - 0
config/src/test/java/org/springframework/security/config/http/CsrfConfigTests.java

@@ -0,0 +1,646 @@
+/*
+ * Copyright 2002-2018 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.config.http;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpSession;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.config.test.SpringTestContext;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.test.context.annotation.SecurityTestExecutionListeners;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.security.test.web.support.WebTestUtils;
+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.util.matcher.RequestMatcher;
+import org.springframework.stereotype.Controller;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultMatcher;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.servlet.support.RequestDataValueProcessor;
+
+import javax.servlet.Filter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URI;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
+import static org.springframework.web.bind.annotation.RequestMethod.GET;
+import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
+import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS;
+import static org.springframework.web.bind.annotation.RequestMethod.PATCH;
+import static org.springframework.web.bind.annotation.RequestMethod.POST;
+import static org.springframework.web.bind.annotation.RequestMethod.PUT;
+import static org.springframework.web.bind.annotation.RequestMethod.TRACE;
+
+/**
+ *
+ * @author Rob Winch
+ * @author Josh Cummings
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SecurityTestExecutionListeners
+public class CsrfConfigTests {
+	private static final String CONFIG_LOCATION_PREFIX =
+			"classpath:org/springframework/security/config/http/CsrfConfigTests";
+
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Autowired
+	MockMvc mvc;
+
+	@Test
+	public void postWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(post("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void putWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(put("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void patchWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(patch("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void deleteWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(delete("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void invalidWhenDefaultConfigurationThenForbiddenSinceCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(request("INVALID", new URI("/csrf")))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void getWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(get("/csrf"))
+				.andExpect(csrfInBody());
+	}
+
+
+	@Test
+	public void headWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(head("/csrf-in-header"))
+				.andExpect(csrfInHeader());
+	}
+
+	@Test
+	public void traceWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		MockMvc traceEnabled = MockMvcBuilders
+				.webAppContextSetup((WebApplicationContext) this.spring.getContext())
+				.apply(springSecurity())
+				.addDispatcherServletCustomizer(dispatcherServlet -> dispatcherServlet.setDispatchTraceRequest(true))
+				.build();
+
+		traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header"))
+				.andExpect(csrfInHeader());
+	}
+
+	@Test
+	public void optionsWhenDefaultConfigurationThenCsrfIsEnabled() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		this.mvc.perform(options("/csrf-in-header"))
+				.andExpect(csrfInHeader());
+	}
+
+	@Test
+	public void postWhenCsrfDisabledThenRequestAllowed() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("CsrfDisabled")
+			).autowire();
+
+		this.mvc.perform(post("/ok"))
+				.andExpect(status().isOk());
+
+		assertThat(getFilter(this.spring, CsrfFilter.class)).isNull();
+	}
+
+	@Test
+	public void postWhenCsrfElementEnabledThenForbidden() throws Exception {
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(post("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void putWhenCsrfElementEnabledThenForbidden() throws Exception {
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(put("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void patchWhenCsrfElementEnabledThenForbidden() throws Exception {
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(patch("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void deleteWhenCsrfElementEnabledThenForbidden() throws Exception {
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(delete("/csrf"))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void invalidWhenCsrfElementEnabledThenForbidden() throws Exception {
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(request("INVALID", new URI("/csrf")))
+				.andExpect(status().isForbidden())
+				.andExpect(csrfCreated());
+	}
+
+	@Test
+	public void getWhenCsrfElementEnabledThenOk() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(get("/csrf"))
+				.andExpect(csrfInBody());
+	}
+
+	@Test
+	public void headWhenCsrfElementEnabledThenOk() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(head("/csrf-in-header"))
+				.andExpect(csrfInHeader());
+	}
+
+	@Test
+	public void traceWhenCsrfElementEnabledThenOk() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		MockMvc traceEnabled = MockMvcBuilders
+				.webAppContextSetup((WebApplicationContext) this.spring.getContext())
+				.apply(springSecurity())
+				.addDispatcherServletCustomizer(dispatcherServlet -> dispatcherServlet.setDispatchTraceRequest(true))
+				.build();
+
+		traceEnabled.perform(request(HttpMethod.TRACE, "/csrf-in-header"))
+				.andExpect(csrfInHeader());
+	}
+
+	@Test
+	public void optionsWhenCsrfElementEnabledThenOk() throws Exception {
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(options("/csrf-in-header"))
+				.andExpect(csrfInHeader());
+	}
+
+	@Test
+	public void autowireWhenCsrfElementEnabledThenCreatesCsrfRequestDataValueProcessor() {
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		assertThat(this.spring.getContext().getBean(RequestDataValueProcessor.class)).isNotNull();
+	}
+
+	@Test
+	public void postWhenUsingCsrfAndCustomAccessDeniedHandlerThenTheHandlerIsAppropriatelyEngaged()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("WithAccessDeniedHandler"),
+				this.xml("shared-access-denied-handler")
+			).autowire();
+
+		this.mvc.perform(post("/ok"))
+				.andExpect(status().isIAmATeapot());
+	}
+
+	@Test
+	public void postWhenHasCsrfTokenButSessionExpiresThenRequestIsCancelledAfterSuccessfulAuthentication()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		// simulates a request that has no authentication (e.g. session time-out)
+		MvcResult result = this.mvc.perform(post("/authenticated")
+												.with(csrf()))
+								.andExpect(redirectedUrl("http://localhost/login"))
+								.andReturn();
+
+		MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
+
+		// if the request cache is consulted, then it will redirect back to /some-url, which we don't want
+		this.mvc.perform(post("/login")
+							.param("username", "user")
+							.param("password", "password")
+							.session(session)
+							.with(csrf()))
+				.andExpect(redirectedUrl("/"));
+	}
+
+	@Test
+	public void getWhenHasCsrfTokenButSessionExpiresThenRequestIsRememeberedAfterSuccessfulAuthentication()
+			throws Exception {
+
+		this.spring.configLocations(
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		// simulates a request that has no authentication (e.g. session time-out)
+		MvcResult result =
+				this.mvc.perform(get("/authenticated"))
+						.andExpect(redirectedUrl("http://localhost/login"))
+						.andReturn();
+
+		MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
+
+		// if the request cache is consulted, then it will redirect back to /some-url, which we do want
+		this.mvc.perform(post("/login")
+							.param("username", "user")
+							.param("password", "password")
+							.session(session)
+							.with(csrf()))
+				.andExpect(redirectedUrl("http://localhost/authenticated"));
+	}
+
+	/**
+	 * SEC-2422: csrf expire CSRF token and session-management invalid-session-url
+	 */
+	@Test
+	public void postWhenUsingCsrfAndCustomSessionManagementAndNoSessionThenStillRedirectsToInvalidSessionUrl()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("WithSessionManagement")
+			).autowire();
+
+		MvcResult result = this.mvc.perform(post("/ok").param("_csrf", "abc"))
+								.andExpect(redirectedUrl("/error/sessionError"))
+								.andReturn();
+
+		MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
+
+		this.mvc.perform(post("/csrf")
+							.session(session))
+					.andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void requestWhenUsingCustomRequestMatcherConfiguredThenAppliesAccordingly()
+		throws Exception {
+
+		SpringTestContext context =
+				this.spring.configLocations(
+						this.xml("shared-controllers"),
+						this.xml("WithRequestMatcher"),
+						this.xml("mock-request-matcher")
+				);
+
+		context.autowire();
+
+		RequestMatcher matcher = context.getContext().getBean(RequestMatcher.class);
+		when(matcher.matches(any(HttpServletRequest.class))).thenReturn(false);
+
+		this.mvc.perform(post("/ok")).andExpect(status().isOk());
+
+		when(matcher.matches(any(HttpServletRequest.class))).thenReturn(true);
+
+		this.mvc.perform(get("/ok")).andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void getWhenDefaultConfigurationThenSessionNotImmediatelyCreated()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		MvcResult result = this.mvc.perform(get("/ok"))
+								.andExpect(status().isOk())
+								.andReturn();
+
+		assertThat(result.getRequest().getSession(false)).isNull();
+	}
+
+	@Test
+	@WithMockUser
+	public void postWhenCsrfMismatchesThenForbidden()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		MvcResult result = this.mvc.perform(get("/ok")).andReturn();
+
+		MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
+
+		this.mvc.perform(post("/ok")
+							.session(session)
+							.with(csrf().useInvalidToken()))
+				.andExpect(status().isForbidden());
+	}
+
+	@Test
+	public void loginWhenDefaultConfigurationThenCsrfCleared()
+			throws Exception {
+
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		MvcResult result = this.mvc.perform(get("/csrf")).andReturn();
+
+		MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
+
+		this.mvc.perform(post("/login")
+							.param("username", "user")
+							.param("password", "password")
+							.session(session)
+							.with(csrf()))
+			.andExpect(status().isFound());
+
+		this.mvc.perform(get("/csrf").session(session))
+				.andExpect(csrfChanged(result));
+	}
+
+	@Test
+	public void logoutWhenDefaultConfigurationThenCsrfCleared()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("AutoConfig")
+			).autowire();
+
+		MvcResult result = this.mvc.perform(get("/csrf")).andReturn();
+
+		MockHttpSession session = (MockHttpSession) result.getRequest().getSession();
+
+		this.mvc.perform(post("/logout").session(session)
+							.with(csrf()))
+				.andExpect(status().isFound());
+
+		this.mvc.perform(get("/csrf").session(session))
+				.andExpect(csrfChanged(result));
+	}
+
+	/**
+	 * SEC-2495: csrf disables logout on GET
+	 */
+	@Test
+	@WithMockUser
+	public void logoutWhenDefaultConfigurationThenDisabled()
+		throws Exception {
+
+		this.spring.configLocations(
+				this.xml("shared-controllers"),
+				this.xml("CsrfEnabled")
+			).autowire();
+
+		this.mvc.perform(get("/logout")).andExpect(status().isNotFound());
+
+		// still logged in
+		this.mvc.perform(get("/authenticated")).andExpect(status().isOk());
+	}
+
+	private <T extends Filter> T getFilter(SpringTestContext context, Class<T> type) {
+		FilterChainProxy chain = context.getContext().getBean(FilterChainProxy.class);
+
+		List<Filter> filters = chain.getFilters("/any");
+
+		for ( Filter filter : filters ) {
+			if ( type.isAssignableFrom(filter.getClass()) ) {
+				return (T) filter;
+			}
+		}
+
+		return null;
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
+	@Controller
+	public static class RootController {
+		@RequestMapping(value = "/csrf-in-header", method = { HEAD, TRACE, OPTIONS })
+		@ResponseBody
+		String csrfInHeaderAndBody(CsrfToken token, HttpServletResponse response) {
+			response.setHeader(token.getHeaderName(), token.getToken());
+			return csrfInBody(token);
+		}
+
+		@RequestMapping(value = "/csrf", method = { POST, PUT, PATCH, DELETE, GET })
+		@ResponseBody
+		String csrfInBody(CsrfToken token) {
+			return token.getToken();
+		}
+
+		@RequestMapping(value = "/ok", method = { POST, GET })
+		@ResponseBody
+		String ok() {
+			return "ok";
+		}
+
+		@GetMapping("/authenticated")
+		@ResponseBody
+		String authenticated() {
+			return "authenticated";
+		}
+	}
+
+	private static class TeapotAccessDeniedHandler implements AccessDeniedHandler {
+
+		@Override
+		public void handle(
+				HttpServletRequest request,
+				HttpServletResponse response,
+				AccessDeniedException accessDeniedException) {
+
+			response.setStatus(HttpStatus.IM_A_TEAPOT_418);
+		}
+	}
+
+	ResultMatcher csrfChanged(MvcResult first) {
+		return (second) -> {
+			assertThat(first).isNotNull();
+			assertThat(second).isNotNull();
+			assertThat(first.getResponse().getContentAsString())
+					.isNotEqualTo(second.getResponse().getContentAsString());
+		};
+	}
+
+	ResultMatcher csrfCreated() {
+		return new CsrfCreatedResultMatcher();
+	}
+
+	ResultMatcher csrfInHeader() {
+		return new CsrfReturnedResultMatcher(result -> result.getResponse().getHeader("X-CSRF-TOKEN"));
+	}
+
+	ResultMatcher csrfInBody() {
+		return new CsrfReturnedResultMatcher(result -> result.getResponse().getContentAsString());
+	}
+
+	@FunctionalInterface
+	interface ExceptionalFunction<IN, OUT> {
+		OUT apply(IN in) throws Exception;
+	}
+
+	static class CsrfCreatedResultMatcher implements ResultMatcher {
+		@Override
+		public void match(MvcResult result) throws Exception {
+			MockHttpServletRequest request = result.getRequest();
+			CsrfToken token = WebTestUtils.getCsrfTokenRepository(request).loadToken(request);
+			assertThat(token).isNotNull();
+		}
+	}
+
+	static class CsrfReturnedResultMatcher implements ResultMatcher {
+		ExceptionalFunction<MvcResult, String> token;
+
+		public CsrfReturnedResultMatcher(ExceptionalFunction<MvcResult, String> token) {
+			this.token = token;
+		}
+
+		@Override
+		public void match(MvcResult result) throws Exception {
+			MockHttpServletRequest request = result.getRequest();
+			CsrfToken token = WebTestUtils.getCsrfTokenRepository(request).loadToken(request);
+			assertThat(token).isNotNull();
+			assertThat(token.getToken()).isEqualTo(this.token.apply(result));
+		}
+	}
+
+}

+ 27 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-AutoConfig.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true"/>
+
+	<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
+</b:beans>

+ 29 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfDisabled.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<csrf disabled="true"/>
+	</http>
+
+	<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
+</b:beans>

+ 30 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<intercept-url pattern="/authenticated/**" access="authenticated"/>
+		<csrf/>
+	</http>
+
+	<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
+</b:beans>

+ 30 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-WithAccessDeniedHandler.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true">
+		<access-denied-handler ref="accessDeniedHandler"/>
+		<csrf/>
+	</http>
+
+	<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
+</b:beans>

+ 29 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-WithRequestMatcher.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true" use-expressions="false">
+		<csrf request-matcher-ref="requestMatcher"/>
+	</http>
+
+	<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
+</b:beans>

+ 30 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-WithSessionManagement.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http auto-config="true" use-expressions="false">
+		<session-management invalid-session-url="/error/sessionError"/>
+		<csrf/>
+	</http>
+
+	<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
+</b:beans>

+ 28 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-mock-csrf-token-repository.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<b:bean id="csrfTokenRepository" class="org.mockito.Mockito" factory-method="mock">
+		<b:constructor-arg value="org.springframework.security.web.csrf.CsrfTokenRepository"/>
+		<b:constructor-arg value="csrfTokenRepository"/>
+	</b:bean>
+
+</b:beans>

+ 27 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-mock-request-matcher.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<b:bean id="requestMatcher" class="org.mockito.Mockito" factory-method="mock">
+		<b:constructor-arg value="org.springframework.security.web.util.matcher.RequestMatcher"/>
+		<b:constructor-arg value="requestMatcher"/>
+	</b:bean>
+</b:beans>

+ 25 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-access-denied-handler.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<b:bean id="accessDeniedHandler" class="org.springframework.security.config.http.CsrfConfigTests.TeapotAccessDeniedHandler"/>
+
+</b:beans>

+ 33 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-controllers.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:mvc="http://www.springframework.org/schema/mvc"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+	<mvc:annotation-driven>
+		<mvc:argument-resolvers>
+			<b:bean class="org.springframework.security.web.method.annotation.CsrfTokenArgumentResolver"/>
+		</mvc:argument-resolvers>
+	</mvc:annotation-driven>
+
+	<b:bean class="org.springframework.security.config.http.CsrfConfigTests.RootController"/>
+
+</b:beans>

+ 25 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-csrf-token-repository.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<b:bean id="csrfTokenRepository" class="org.springframework.security.config.http.CsrfConfigTests.TeapotCsrfTokenRepository"/>
+
+</b:beans>

+ 26 - 0
config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-shared-userservice.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns="http://www.springframework.org/schema/security"
+	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+	<user-service>
+		<user name="user" password="{noop}password" authorities="ROLE_USER"/>
+	</user-service>
+</b:beans>