From d9d4cc2ef5ab40f55e7a0cde68b1a5e78aefb4b3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 27 Oct 2015 10:50:05 +0000 Subject: [PATCH] Ensure request context is setup before security filter runs Previously, OrderedRequestContextFilter was ordered such that it ran after Spring Security's Filter. This meant that the request context was unavailable to any Filters in Spring Security's Filter chain. Specifically, this caused a failure when using @EnableOAuth2Sso as OAuth2ClientAuthenticationProcessingFilter, which is added to Spring Security's Filter chain would be unable to use the request-scoped bean upon which it depends. This commit updates the order of OrderedRequestContextFilter so that the request context is set up before Spring Security's Filter runs. The tests for SampleGitHubApplication have been updated to use TestRestTemplate rather than MockMvc. This is necessary as the latter, via ServletTestExecutionListener, automatically populates the request context holder, masking the fact that the request context filter was setting it up too late. Closes gh-4270 --- .../github/SampleGithubApplicationTests.java | 63 +++++++++---------- .../web/OrderedRequestContextFilter.java | 2 +- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/spring-boot-samples/spring-boot-sample-web-secure-github/src/test/java/sample/web/secure/github/SampleGithubApplicationTests.java b/spring-boot-samples/spring-boot-sample-web-secure-github/src/test/java/sample/web/secure/github/SampleGithubApplicationTests.java index 095f64c9fc..8964d41044 100644 --- a/spring-boot-samples/spring-boot-sample-web-secure-github/src/test/java/sample/web/secure/github/SampleGithubApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-web-secure-github/src/test/java/sample/web/secure/github/SampleGithubApplicationTests.java @@ -16,65 +16,58 @@ package sample.web.secure.github; -import org.junit.Before; +import java.net.URI; + import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; -import org.springframework.security.web.FilterChainProxy; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.context.WebApplicationContext; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertThat; /** - * Basic integration tests for github sso application. + * Basic integration tests for GitHub SSO application. * * @author Dave Syer + * @author Andy Wilkinson */ @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(SampleGithubSecureApplication.class) -@WebAppConfiguration +@WebIntegrationTest(randomPort = true) @DirtiesContext public class SampleGithubApplicationTests { - @Autowired - private WebApplicationContext context; - - @Autowired - private FilterChainProxy filterChain; - - @Autowired - private OAuth2ClientContextFilter filter; - - private MockMvc mvc; - - @Before - public void setUp() { - this.mvc = webAppContextSetup(this.context) - .addFilters(this.filter, this.filterChain).build(); - SecurityContextHolder.clearContext(); - } + @Value("${local.server.port}") + private int port; @Test public void everythingIsSecuredByDefault() throws Exception { - this.mvc.perform(get("/")).andExpect(status().isFound()) - .andExpect(redirectedUrlPattern("**/login")); + TestRestTemplate restTemplate = new TestRestTemplate(); + ResponseEntity entity = restTemplate + .getForEntity("http://localhost:" + this.port, Void.class); + assertThat(entity.getStatusCode(), is(HttpStatus.FOUND)); + assertThat(entity.getHeaders().getLocation(), + is(equalTo(URI.create("http://localhost:" + this.port + "/login")))); } @Test public void loginRedirectsToGithub() throws Exception { - this.mvc.perform(get("/login")).andExpect(status().isFound()) - .andExpect(redirectedUrlPattern("https://github.com/**")); + TestRestTemplate restTemplate = new TestRestTemplate(); + ResponseEntity entity = restTemplate + .getForEntity("http://localhost:" + this.port + "/login", Void.class); + assertThat(entity.getStatusCode(), is(HttpStatus.FOUND)); + assertThat(entity.getHeaders().getLocation().toString(), + startsWith("https://github.com/login/oauth")); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java index 5fea62ffd7..40ed97e14b 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java @@ -29,7 +29,7 @@ import org.springframework.web.filter.RequestContextFilter; public class OrderedRequestContextFilter extends RequestContextFilter implements Ordered { // Order defaults to after Spring Session filter - private int order = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER + 5; + private int order = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 105; @Override public int getOrder() {