diff --git a/config/src/test/groovy/org/springframework/security/config/http/PlaceHolderAndELConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/PlaceHolderAndELConfigTests.groovy deleted file mode 100644 index 13db6f1724..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/http/PlaceHolderAndELConfigTests.groovy +++ /dev/null @@ -1,156 +0,0 @@ -package org.springframework.security.config.http - -import java.text.MessageFormat - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer -import org.springframework.mock.web.MockFilterChain -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpServletResponse -import org.springframework.security.access.SecurityConfig -import org.springframework.security.config.BeanIds -import org.springframework.security.util.FieldUtils -import org.springframework.security.web.PortMapperImpl -import org.springframework.security.web.access.ExceptionTranslationFilter -import org.springframework.security.web.access.channel.ChannelProcessingFilter -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - -class PlaceHolderAndELConfigTests extends AbstractHttpConfigTests { - - def setup() { - // Add a PropertyPlaceholderConfigurer to the context for all the tests - bean(PropertyPlaceholderConfigurer.class.name, PropertyPlaceholderConfigurer.class) - } - - def unsecuredPatternSupportsPlaceholderForPattern() { - System.setProperty("pattern.nofilters", "/unprotected"); - - xml.http(pattern: '${pattern.nofilters}', security: 'none') - httpAutoConfig() { - interceptUrl('/**', 'ROLE_A') - } - createAppContext() - - List filters = getFilters("/unprotected"); - - expect: - filters.size() == 0 - } - - // SEC-1201 - def interceptUrlsAndFormLoginSupportPropertyPlaceholders() { - System.setProperty("secure.Url", "/secure"); - System.setProperty("secure.role", "ROLE_A"); - System.setProperty("login.page", "/loginPage"); - System.setProperty("default.target", "/defaultTarget"); - System.setProperty("auth.failure", "/authFailure"); - - xml.http(pattern: '${login.page}', security: 'none') - xml.http('use-expressions':false) { - interceptUrl('${secure.Url}', '${secure.role}') - 'form-login'('login-page':'${login.page}', 'default-target-url': '${default.target}', - 'authentication-failure-url':'${auth.failure}'); - } - createAppContext(); - - expect: - propertyValuesMatchPlaceholders() - getFilters("/loginPage").size() == 0 - } - - // SEC-1309 - def interceptUrlsAndFormLoginSupportEL() { - System.setProperty("secure.url", "/secure"); - System.setProperty("secure.role", "ROLE_A"); - System.setProperty("login.page", "/loginPage"); - System.setProperty("default.target", "/defaultTarget"); - System.setProperty("auth.failure", "/authFailure"); - - xml.http('use-expressions':false) { - interceptUrl("#{systemProperties['secure.url']}", "#{systemProperties['secure.role']}") - 'form-login'('login-page':"#{systemProperties['login.page']}", 'default-target-url': "#{systemProperties['default.target']}", - 'authentication-failure-url':"#{systemProperties['auth.failure']}"); - } - createAppContext() - - expect: - propertyValuesMatchPlaceholders() - } - - private void propertyValuesMatchPlaceholders() { - // Check the security attribute - def fis = getFilter(FilterSecurityInterceptor); - def fids = fis.getSecurityMetadataSource(); - Collection attrs = fids.getAttributes(createFilterinvocation("/secure", null)); - assert attrs.size() == 1 - assert attrs.contains(new SecurityConfig("ROLE_A")) - - // Check the form login properties are set - def apf = getFilter(UsernamePasswordAuthenticationFilter) - assert FieldUtils.getFieldValue(apf, "successHandler.defaultTargetUrl") == '/defaultTarget' - assert "/authFailure" == FieldUtils.getFieldValue(apf, "failureHandler.defaultFailureUrl") - - def etf = getFilter(ExceptionTranslationFilter) - assert "/loginPage"== etf.authenticationEntryPoint.loginFormUrl - } - - def portMappingsWorkWithPlaceholdersAndEL() { - System.setProperty("http", "9080"); - System.setProperty("https", "9443"); - - httpAutoConfig { - 'port-mappings'() { - 'port-mapping'(http: '#{systemProperties.http}', https: '${https}') - } - } - createAppContext(); - - def pm = (appContext.getBeansOfType(PortMapperImpl).values() as List)[0]; - - expect: - pm.getTranslatedPortMappings().size() == 1 - pm.lookupHttpPort(9443) == 9080 - pm.lookupHttpsPort(9080) == 9443 - } - - def requiresChannelSupportsPlaceholder() { - System.setProperty("secure.url", "/secure"); - System.setProperty("required.channel", "https"); - - httpAutoConfig { - 'intercept-url'(pattern: '${secure.url}', 'requires-channel': '${required.channel}') - } - createAppContext(); - List filters = getFilters("/secure"); - - expect: - filters.size() == AUTO_CONFIG_FILTERS + 1 - filters[0] instanceof ChannelProcessingFilter - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setServletPath("/secure"); - MockHttpServletResponse response = new MockHttpServletResponse(); - filters[0].doFilter(request, response, new MockFilterChain()); - response.getRedirectedUrl().startsWith("https") - } - - def accessDeniedPageWorksWithPlaceholders() { - System.setProperty("accessDenied", "/go-away"); - xml.http('auto-config': 'true') { - 'access-denied-handler'('error-page' : '${accessDenied}') {} - } - createAppContext(); - - expect: - FieldUtils.getFieldValue(getFilter(ExceptionTranslationFilter.class), "accessDeniedHandler.errorPage") == '/go-away' - } - - def accessDeniedHandlerPageWorksWithEL() { - httpAutoConfig { - 'access-denied-handler'('error-page': "#{'/go' + '-away'}") - } - createAppContext() - - expect: - getFilter(ExceptionTranslationFilter).accessDeniedHandler.errorPage == '/go-away' - } -} diff --git a/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java b/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java new file mode 100644 index 0000000000..070cf441b7 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/http/PlaceHolderAndELConfigTests.java @@ -0,0 +1,212 @@ +/* + * 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.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +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.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Josh Cummings + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SecurityTestExecutionListeners +public class PlaceHolderAndELConfigTests { + + private static final String CONFIG_LOCATION_PREFIX = + "classpath:org/springframework/security/config/http/PlaceHolderAndELConfigTests"; + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + MockMvc mvc; + + @Test + public void getWhenUsingPlaceholderThenUnsecuredPatternCorrectlyConfigured() + throws Exception { + + System.setProperty("pattern.nofilters", "/unsecured"); + + this.spring.configLocations(this.xml("UnsecuredPattern")).autowire(); + + this.mvc.perform(get("/unsecured")) + .andExpect(status().isOk()); + } + + /** + * SEC-1201 + */ + @Test + public void loginWhenUsingPlaceholderThenInterceptUrlsAndFormLoginWorks() + throws Exception { + + System.setProperty("secure.Url", "/secured"); + System.setProperty("secure.role", "ROLE_NUNYA"); + System.setProperty("login.page", "/loginPage"); + System.setProperty("default.target", "/defaultTarget"); + System.setProperty("auth.failure", "/authFailure"); + + this.spring.configLocations(this.xml("InterceptUrlAndFormLogin")).autowire(); + + // login-page setting + + this.mvc.perform(get("/secured")) + .andExpect(redirectedUrl("http://localhost/loginPage")); + + // login-processing-url setting + // default-target-url setting + + this.mvc.perform(post("/loginPage") + .param("username", "user") + .param("password", "password")) + .andExpect(redirectedUrl("/defaultTarget")); + + // authentication-failure-url setting + + this.mvc.perform(post("/loginPage") + .param("username", "user") + .param("password", "wrong")) + .andExpect(redirectedUrl("/authFailure")); + } + + /** + * SEC-1309 + */ + @Test + public void loginWhenUsingSpELThenInterceptUrlsAndFormLoginWorks() + throws Exception { + + System.setProperty("secure.url", "/secured"); + System.setProperty("secure.role", "ROLE_NUNYA"); + System.setProperty("login.page", "/loginPage"); + System.setProperty("default.target", "/defaultTarget"); + System.setProperty("auth.failure", "/authFailure"); + + this.spring.configLocations( + this.xml("InterceptUrlAndFormLoginWithSpEL")).autowire(); + + // login-page setting + + this.mvc.perform(get("/secured")) + .andExpect(redirectedUrl("http://localhost/loginPage")); + + // login-processing-url setting + // default-target-url setting + + this.mvc.perform(post("/loginPage") + .param("username", "user") + .param("password", "password")) + .andExpect(redirectedUrl("/defaultTarget")); + + // authentication-failure-url setting + + this.mvc.perform(post("/loginPage") + .param("username", "user") + .param("password", "wrong")) + .andExpect(redirectedUrl("/authFailure")); + + } + + @Test + @WithMockUser + public void requestWhenUsingPlaceholderOrSpELThenPortMapperWorks() + throws Exception { + + System.setProperty("http", "9080"); + System.setProperty("https", "9443"); + + this.spring.configLocations(this.xml("PortMapping")).autowire(); + + this.mvc.perform(get("http://localhost:9080/secured")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("https://localhost:9443/secured")); + + this.mvc.perform(get("https://localhost:9443/unsecured")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost:9080/unsecured")); + } + + @Test + @WithMockUser + public void requestWhenUsingPlaceholderThenRequiresChannelWorks() + throws Exception { + + System.setProperty("secure.url", "/secured"); + System.setProperty("required.channel", "https"); + + this.spring.configLocations(this.xml("RequiresChannel")).autowire(); + + this.mvc.perform(get("http://localhost/secured")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("https://localhost/secured")); + } + + @Test + @WithMockUser + public void requestWhenUsingPlaceholderThenAccessDeniedPageWorks() + throws Exception { + + System.setProperty("accessDenied", "/go-away"); + + this.spring.configLocations(this.xml("AccessDeniedPage")).autowire(); + + this.mvc.perform(get("/secured")) + .andExpect(forwardedUrl("/go-away")); + } + + @Test + @WithMockUser + public void requestWhenUsingSpELThenAccessDeniedPageWorks() + throws Exception { + + this.spring.configLocations(this.xml("AccessDeniedPageWithSpEL")).autowire(); + + this.mvc.perform(get("/secured")) + .andExpect(forwardedUrl("/go-away")); + } + + @RestController + static class SimpleController { + @GetMapping("/unsecured") + String unsecured() { + return "unsecured"; + } + + @GetMapping("/secured") + String secured() { + return "secured"; + } + } + + private String xml(String configName) { + return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml"; + } +} diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml new file mode 100644 index 0000000000..04f10d3d00 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPage.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml new file mode 100644 index 0000000000..d4f67486e0 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-AccessDeniedPageWithSpEL.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml new file mode 100644 index 0000000000..be48c5b85d --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLogin.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml new file mode 100644 index 0000000000..93e955f756 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-InterceptUrlAndFormLoginWithSpEL.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml new file mode 100644 index 0000000000..c135a75b08 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-PortMapping.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml new file mode 100644 index 0000000000..1d9c90488d --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-RequiresChannel.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml new file mode 100644 index 0000000000..139a459c76 --- /dev/null +++ b/config/src/test/resources/org/springframework/security/config/http/PlaceHolderAndELConfigTests-UnsecuredPattern.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + +