From 1d0bb08398b9aa9afe84be6a5118bf59fd2633f0 Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Mon, 2 Jul 2018 10:39:24 -0600 Subject: [PATCH] InterceptUrlConfigTests groovy->java Issue: gh-4939 --- .../http/InterceptUrlConfigTests.groovy | 400 ------------------ .../config/http/InterceptUrlConfigTests.java | 293 +++++++++++++ ...ptUrlConfigTests-AntMatcherServletPath.xml | 33 ++ ...tUrlConfigTests-CamelCasePathVariables.xml | 36 ++ ...lConfigTests-CiRegexMatcherServletPath.xml | 33 ++ ...lConfigTests-DefaultMatcherServletPath.xml | 33 ++ .../InterceptUrlConfigTests-HasAnyRole.xml | 35 ++ .../InterceptUrlConfigTests-MvcMatchers.xml | 40 ++ ...rlConfigTests-MvcMatchersPathVariables.xml | 41 ++ ...tUrlConfigTests-MvcMatchersServletPath.xml | 40 ++ .../InterceptUrlConfigTests-PatchMethod.xml | 36 ++ .../InterceptUrlConfigTests-PathVariables.xml | 36 ++ ...UrlConfigTests-RegexMatcherServletPath.xml | 33 ++ .../http/InterceptUrlConfigTests-Sec2256.xml | 37 ++ ...onfigTests-TypeConversionPathVariables.xml | 37 ++ .../security/config/http/userservice.xml | 1 + 16 files changed, 764 insertions(+), 400 deletions(-) delete mode 100644 config/src/test/groovy/org/springframework/security/config/http/InterceptUrlConfigTests.groovy create mode 100644 config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AntMatcherServletPath.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CiRegexMatcherServletPath.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-HasAnyRole.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchers.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersPathVariables.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersServletPath.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-RegexMatcherServletPath.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml create mode 100644 config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml diff --git a/config/src/test/groovy/org/springframework/security/config/http/InterceptUrlConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/InterceptUrlConfigTests.groovy deleted file mode 100644 index c0f3d1fe09..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/http/InterceptUrlConfigTests.groovy +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2002-2017 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.ServletContext -import javax.servlet.ServletRegistration -import javax.servlet.http.HttpServletResponse - -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer - -import org.springframework.beans.factory.parsing.BeanDefinitionParsingException -import org.springframework.mock.web.MockFilterChain -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpServletResponse -import org.springframework.mock.web.MockServletContext -import org.springframework.security.access.SecurityConfig -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController - -import static org.mockito.Mockito.* -/** - * - * @author Rob Winch - */ -class InterceptUrlConfigTests extends AbstractHttpConfigTests { - - def "SEC-2256: intercept-url method is not given priority"() { - when: - httpAutoConfig { - 'intercept-url'(pattern: '/anyurl', access: "ROLE_USER") - 'intercept-url'(pattern: '/anyurl', 'method':'GET',access: 'ROLE_ADMIN') - } - createAppContext() - - def fids = getFilter(FilterSecurityInterceptor).securityMetadataSource - def attrs = fids.getAttributes(createFilterinvocation("/anyurl", "GET")) - def attrsPost = fids.getAttributes(createFilterinvocation("/anyurl", "POST")) - - then: - attrs.size() == 1 - attrs.contains(new SecurityConfig("ROLE_USER")) - attrsPost.size() == 1 - attrsPost.contains(new SecurityConfig("ROLE_USER")) - } - - def "SEC-2355: intercept-url support patch"() { - setup: - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('use-expressions':false) { - 'http-basic'() - 'intercept-url'(pattern: '/**', 'method':'PATCH',access: 'ROLE_ADMIN') - csrf(disabled:true) - } - createAppContext() - when: 'Method other than PATCH is used' - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_OK - when: 'Method of PATCH is used' - request = new MockHttpServletRequest(method:'PATCH') - response = new MockHttpServletResponse() - chain = new MockFilterChain() - springSecurityFilterChain.doFilter(request, response, chain) - then: 'The response is unauthorized' - response.status == HttpServletResponse.SC_UNAUTHORIZED - } - - def "intercept-url supports hasAnyRoles"() { - setup: - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('use-expressions':true) { - 'http-basic'() - 'intercept-url'(pattern: '/**', access: "hasAnyRole('ROLE_DEVELOPER','ROLE_USER')") - csrf(disabled:true) - } - when: - createAppContext() - then: 'no error' - noExceptionThrown() - when: 'ROLE_USER can access' - login(request, 'user', 'password') - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_OK - when: 'ROLE_A cannot access' - request = new MockHttpServletRequest(method:'GET') - response = new MockHttpServletResponse() - chain = new MockFilterChain() - login(request, 'bob', 'bobspassword') - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is Forbidden' - response.status == HttpServletResponse.SC_FORBIDDEN - } - - def "SEC-2256: intercept-url supports path variables"() { - setup: - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('use-expressions':true) { - 'http-basic'() - 'intercept-url'(pattern: '/user/{un}/**', access: "#un == authentication.name") - 'intercept-url'(pattern: '/**', access: "denyAll") - } - createAppContext() - login(request, 'user', 'password') - when: 'user can access' - request.servletPath = '/user/user/abc' - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_OK - when: 'user cannot access otheruser' - request = new MockHttpServletRequest(method:'GET', servletPath : '/user/otheruser/abc') - login(request, 'user', 'password') - response = new MockHttpServletResponse() - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - when: 'user can access case insensitive URL' - request = new MockHttpServletRequest(method:'GET', servletPath : '/USER/user/abc') - login(request, 'user', 'password') - response = new MockHttpServletResponse() - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - } - - def "gh-3786 intercept-url supports cammel case path variables"() { - setup: - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('use-expressions':true) { - 'http-basic'() - 'intercept-url'(pattern: '/user/{userName}/**', access: "#userName == authentication.name") - 'intercept-url'(pattern: '/**', access: "denyAll") - } - createAppContext() - login(request, 'user', 'password') - when: 'user can access' - request.servletPath = '/user/user/abc' - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_OK - when: 'user cannot access otheruser' - request = new MockHttpServletRequest(method:'GET', servletPath : '/user/otheruser/abc') - login(request, 'user', 'password') - response = new MockHttpServletResponse() - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - when: 'user can access case insensitive URL' - request = new MockHttpServletRequest(method:'GET', servletPath : '/USER/user/abc') - login(request, 'user', 'password') - response = new MockHttpServletResponse() - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - } - - def "SEC-2256: intercept-url supports path variable type conversion"() { - setup: - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('use-expressions':true) { - 'http-basic'() - 'intercept-url'(pattern: '/user/{un}/**', access: "@id.isOne(#un)") - 'intercept-url'(pattern: '/**', access: "denyAll") - } - bean('id', Id) - createAppContext() - login(request, 'user', 'password') - when: 'can access id == 1' - request.servletPath = '/user/1/abc' - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_OK - when: 'user cannot access 2' - request = new MockHttpServletRequest(method:'GET', servletPath : '/user/2/abc') - login(request, 'user', 'password') - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - } - - def "intercept-url supports mvc matchers"() { - setup: - MockServletContext servletContext = mockServletContext(); - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('request-matcher':'mvc') { - 'http-basic'() - 'intercept-url'(pattern: '/path', access: "denyAll") - } - bean('pathController',PathController) - xml.'mvc:annotation-driven'() - - createWebAppContext(servletContext) - when: - request.servletPath = "/path" - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_UNAUTHORIZED - when: - request = new MockHttpServletRequest(method:'GET') - response = new MockHttpServletResponse() - chain = new MockFilterChain() - request.servletPath = "/path.html" - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_UNAUTHORIZED - when: - request = new MockHttpServletRequest(method:'GET') - response = new MockHttpServletResponse() - chain = new MockFilterChain() - request.servletPath = "/path/" - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_UNAUTHORIZED - } - - def "intercept-url mvc supports path variables"() { - setup: - MockServletContext servletContext = mockServletContext(); - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('request-matcher':'mvc') { - 'http-basic'() - 'intercept-url'(pattern: '/user/{un}/**', access: "#un == 'user'") - } - xml.'mvc:annotation-driven'() - createWebAppContext(servletContext) - when: 'user can access' - request.servletPath = '/user/user/abc' - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_OK - when: 'cannot access otheruser' - request = new MockHttpServletRequest(method:'GET', servletPath : '/user/otheruser/abc') - login(request, 'user', 'password') - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - when: 'user can access case insensitive URL' - request = new MockHttpServletRequest(method:'GET', servletPath : '/USER/user/abc') - login(request, 'user', 'password') - chain.reset() - springSecurityFilterChain.doFilter(request,response,chain) - then: 'The response is OK' - response.status == HttpServletResponse.SC_FORBIDDEN - } - - def "intercept-url mvc matchers with servlet path"() { - setup: - MockServletContext servletContext = mockServletContext("/spring"); - MockHttpServletRequest request = new MockHttpServletRequest(method:'GET') - MockHttpServletResponse response = new MockHttpServletResponse() - MockFilterChain chain = new MockFilterChain() - xml.http('request-matcher':'mvc') { - 'http-basic'() - 'intercept-url'(pattern: '/path', access: "denyAll", 'servlet-path': "/spring") - } - bean('pathController',PathController) - xml.'mvc:annotation-driven'() - createWebAppContext(servletContext) - when: - request.servletPath = "/spring" - request.requestURI = "/spring/path" - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_UNAUTHORIZED - when: - request = new MockHttpServletRequest(method:'GET') - response = new MockHttpServletResponse() - chain = new MockFilterChain() - request.servletPath = "/spring" - request.requestURI = "/spring/path.html" - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_UNAUTHORIZED - when: - request = new MockHttpServletRequest(method:'GET') - response = new MockHttpServletResponse() - chain = new MockFilterChain() - request.servletPath = "/spring" - request.requestURI = "/spring/path/" - springSecurityFilterChain.doFilter(request, response, chain) - then: - response.status == HttpServletResponse.SC_UNAUTHORIZED - } - - def "intercept-url ant matcher with servlet path fails"() { - when: - xml.http('request-matcher':'ant') { - 'http-basic'() - 'intercept-url'(pattern: '/path', access: "denyAll", 'servlet-path': "/spring") - } - createAppContext() - then: - thrown(BeanDefinitionParsingException) - } - - def "intercept-url regex matcher with servlet path fails"() { - when: - xml.http('request-matcher':'regex') { - 'http-basic'() - 'intercept-url'(pattern: '/path', access: "denyAll", 'servlet-path': "/spring") - } - createAppContext() - then: - thrown(BeanDefinitionParsingException) - } - - def "intercept-url ciRegex matcher with servlet path fails"() { - when: - xml.http('request-matcher':'ciRegex') { - 'http-basic'() - 'intercept-url'(pattern: '/path', access: "denyAll", 'servlet-path': "/spring") - } - createAppContext() - then: - thrown(BeanDefinitionParsingException) - } - - def "intercept-url default matcher with servlet path fails"() { - when: - xml.http() { - 'http-basic'() - 'intercept-url'(pattern: '/path', access: "denyAll", 'servlet-path': "/spring") - } - createAppContext() - then: - thrown(BeanDefinitionParsingException) - } - - public static class Id { - public boolean isOne(int i) { - return i == 1; - } - } - - private ServletContext mockServletContext() { - return mockServletContext("/"); - } - - private ServletContext mockServletContext(String servletPath) { - MockServletContext servletContext = spy(new MockServletContext()); - final ServletRegistration registration = mock(ServletRegistration.class); - when(registration.getMappings()).thenReturn(Collections.singleton(servletPath)); - Answer> answer = new Answer>() { - @Override - public Map answer(InvocationOnMock invocation) throws Throwable { - return Collections.singletonMap("spring", registration); - } - }; - when(servletContext.getServletRegistrations()).thenAnswer(answer); - return servletContext; - } - - def login(MockHttpServletRequest request, String username, String password) { - String toEncode = username + ':' + password - request.addHeader('Authorization','Basic ' + Base64.encoder.encodeToString(toEncode.getBytes('UTF-8'))) - } - - @RestController - static class PathController { - @RequestMapping("/path") - public String path() { - return "path"; - } - } -} diff --git a/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java b/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java new file mode 100644 index 0000000000..2de3e5912d --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/http/InterceptUrlConfigTests.java @@ -0,0 +1,293 @@ +/* + * 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.junit.Rule; +import org.junit.Test; +import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.mock.web.MockServletContext; +import org.springframework.security.config.test.SpringTestRule; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.ConfigurableWebApplicationContext; + +import javax.servlet.ServletRegistration; +import java.util.Collections; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +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.result.MockMvcResultMatchers.status; + +/** + * + * @author Rob Winch + * @author Josh Cummings + */ +public class InterceptUrlConfigTests { + + private static final String CONFIG_LOCATION_PREFIX = + "classpath:org/springframework/security/config/http/InterceptUrlConfigTests"; + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + MockMvc mvc; + + /** + * sec-2256 + */ + @Test + public void requestWhenMethodIsSpecifiedThenItIsNotGivenPriority() + throws Exception { + + this.spring.configLocations(this.xml("Sec2256")).autowire(); + + this.mvc.perform(post("/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(get("/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + } + + /** + * sec-2355 + */ + @Test + public void requestWhenUsingPatchThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("PatchMethod")).autowire(); + + this.mvc.perform(get("/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(patch("/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + + this.mvc.perform(patch("/path") + .with(httpBasic("admin", "password"))) + .andExpect(status().isOk()); + + } + + @Test + public void requestWhenUsingHasAnyRoleThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("HasAnyRole")).autowire(); + + this.mvc.perform(get("/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(get("/path") + .with(httpBasic("admin", "password"))) + .andExpect(status().isForbidden()); + } + + /** + * sec-2059 + */ + @Test + public void requestWhenUsingPathVariablesThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("PathVariables")).autowire(); + + this.mvc.perform(get("/path/user/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(get("/path/otheruser/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + + this.mvc.perform(get("/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + } + + /** + * gh-3786 + */ + @Test + public void requestWhenUsingCamelCasePathVariablesThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("CamelCasePathVariables")).autowire(); + + this.mvc.perform(get("/path/user/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(get("/path/otheruser/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + + this.mvc.perform(get("/PATH/user/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + } + + /** + * sec-2059 + */ + @Test + public void requestWhenUsingPathVariablesAndTypeConversionThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("TypeConversionPathVariables")).autowire(); + + this.mvc.perform(get("/path/1/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(get("/path/2/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + + } + + @Test + public void requestWhenUsingMvcMatchersThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("MvcMatchers")).autowire(); + + this.mvc.perform(get("/path")) + .andExpect(status().isUnauthorized()); + + this.mvc.perform(get("/path.html")) + .andExpect(status().isUnauthorized()); + + this.mvc.perform(get("/path/")) + .andExpect(status().isUnauthorized()); + } + + @Test + public void requestWhenUsingMvcMatchersAndPathVariablesThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("MvcMatchersPathVariables")).autowire(); + + this.mvc.perform(get("/path/user/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isOk()); + + this.mvc.perform(get("/path/otheruser/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + + this.mvc.perform(get("/PATH/user/path") + .with(httpBasic("user", "password"))) + .andExpect(status().isForbidden()); + } + + @Test + public void requestWhenUsingMvcMatchersAndServletPathThenAuthorizesRequestsAccordingly() + throws Exception { + + this.spring.configLocations(this.xml("MvcMatchersServletPath")).autowire(); + + MockServletContext servletContext = mockServletContext("/spring"); + ConfigurableWebApplicationContext context = + (ConfigurableWebApplicationContext) this.spring.getContext(); + context.setServletContext(servletContext); + + this.mvc.perform(get("/spring/path").servletPath("/spring")) + .andExpect(status().isUnauthorized()); + + this.mvc.perform(get("/spring/path.html").servletPath("/spring")) + .andExpect(status().isUnauthorized()); + + this.mvc.perform(get("/spring/path/").servletPath("/spring")) + .andExpect(status().isUnauthorized()); + + } + + @Test + public void configureWhenUsingAntMatcherAndServletPathThenThrowsException() { + assertThatCode(() -> this.spring.configLocations(this.xml("AntMatcherServletPath")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class); + } + + @Test + public void configureWhenUsingRegexMatcherAndServletPathThenThrowsException() { + assertThatCode(() -> this.spring.configLocations(this.xml("RegexMatcherServletPath")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class); + } + + @Test + public void configureWhenUsingCiRegexMatcherAndServletPathThenThrowsException() { + assertThatCode(() -> this.spring.configLocations(this.xml("CiRegexMatcherServletPath")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class); + } + + @Test + public void configureWhenUsingDefaultMatcherAndServletPathThenThrowsException() { + assertThatCode(() -> this.spring.configLocations(this.xml("DefaultMatcherServletPath")).autowire()) + .isInstanceOf(BeanDefinitionParsingException.class); + } + + @RestController + static class PathController { + @RequestMapping("/path") + public String path() { + return "path"; + } + + @RequestMapping("/path/{un}/path") + public String path(@PathVariable("un") String name) { + return name; + } + } + + public static class Id { + public boolean isOne(int i) { + return i == 1; + } + } + + private MockServletContext mockServletContext(String servletPath) { + MockServletContext servletContext = spy(new MockServletContext()); + final ServletRegistration registration = mock(ServletRegistration.class); + when(registration.getMappings()).thenReturn(Collections.singleton(servletPath)); + Answer> answer = invocation -> + Collections.singletonMap("spring", registration); + when(servletContext.getServletRegistrations()).thenAnswer(answer); + return servletContext; + } + + private String xml(String configName) { + return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; + } +} diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AntMatcherServletPath.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AntMatcherServletPath.xml new file mode 100644 index 0000000000..c1ddd45cf7 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-AntMatcherServletPath.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml new file mode 100644 index 0000000000..091676e458 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CamelCasePathVariables.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CiRegexMatcherServletPath.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CiRegexMatcherServletPath.xml new file mode 100644 index 0000000000..cb8f4fd6e3 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-CiRegexMatcherServletPath.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml new file mode 100644 index 0000000000..ddf3ebc630 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-DefaultMatcherServletPath.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-HasAnyRole.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-HasAnyRole.xml new file mode 100644 index 0000000000..68e6fe8eba --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-HasAnyRole.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchers.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchers.xml new file mode 100644 index 0000000000..041e070b9f --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchers.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersPathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersPathVariables.xml new file mode 100644 index 0000000000..c7ffba5d9b --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersPathVariables.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersServletPath.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersServletPath.xml new file mode 100644 index 0000000000..365503eda6 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-MvcMatchersServletPath.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml new file mode 100644 index 0000000000..4227abd0e8 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PatchMethod.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml new file mode 100644 index 0000000000..f0ed68089b --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-PathVariables.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-RegexMatcherServletPath.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-RegexMatcherServletPath.xml new file mode 100644 index 0000000000..9c242663f6 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-RegexMatcherServletPath.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml new file mode 100644 index 0000000000..756c38fbba --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-Sec2256.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml new file mode 100644 index 0000000000..8d61391974 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/InterceptUrlConfigTests-TypeConversionPathVariables.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/userservice.xml b/config/src/test/resources/org/springframework/security/config/http/userservice.xml index 80314c3acc..e9eeeceb96 100644 --- a/config/src/test/resources/org/springframework/security/config/http/userservice.xml +++ b/config/src/test/resources/org/springframework/security/config/http/userservice.xml @@ -25,5 +25,6 @@ http://www.springframework.org/schema/beans/spring-beans.xsd"> +