diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/sec2758/Sec2758Tests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/sec2758/Sec2758Tests.groovy deleted file mode 100644 index e65b091ae5..0000000000 --- a/config/src/test/groovy/org/springframework/security/config/annotation/sec2758/Sec2758Tests.groovy +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2002-2013 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.annotation.sec2758; - -import javax.annotation.security.RolesAllowed; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.annotation.Bean; -import org.springframework.core.PriorityOrdered; -import org.springframework.mock.web.MockFilterChain; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource; -import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.authentication.TestingAuthenticationToken -import org.springframework.security.config.annotation.BaseSpringSpec -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.configuration.sec2377.a.* -import org.springframework.security.config.annotation.web.configuration.sec2377.b.* -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler; -import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext - -public class Sec2758Tests extends BaseSpringSpec { - - def cleanup() { - SecurityContextHolder.clearContext() - } - - def "SEC-2758: Verify Passivity Restored with Advice from JIRA"() { - setup: - SecurityContextHolder.context.authentication = new TestingAuthenticationToken("user", "pass", "USER") - loadConfig(SecurityConfig) - Service service = context.getBean(Service) - - when: - findFilter(FilterSecurityInterceptor).doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain()) - then: - noExceptionThrown() - - when: - service.doPreAuthorize() - then: - noExceptionThrown() - - when: - service.doJsr250() - then: - noExceptionThrown() - } - - @EnableWebSecurity - @EnableGlobalMethodSecurity(prePostEnabled=true) - static class SecurityConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests() - .anyRequest().hasAnyAuthority("USER"); - } - - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) { - auth - .inMemoryAuthentication() - .withUser("user").password("password").authorities("USER") - } - - @Bean - Service service() { - return new ServiceImpl() - } - - @Bean - static DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() { - new DefaultRolesPrefixPostProcessor() - } - } - - interface Service { - void doPreAuthorize() - void doJsr250() - } - - static class ServiceImpl implements Service { - @PreAuthorize("hasRole('USER')") - void doPreAuthorize() {} - - @RolesAllowed("USER") - void doJsr250() {} - } - - static class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered { - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - if(bean instanceof Jsr250MethodSecurityMetadataSource) { - ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null); - } - if(bean instanceof DefaultMethodSecurityExpressionHandler) { - ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null); - } - if(bean instanceof DefaultWebSecurityExpressionHandler) { - ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null); - } - return bean; - } - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - - @Override - public int getOrder() { - return PriorityOrdered.HIGHEST_PRECEDENCE; - } -} -} diff --git a/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java new file mode 100644 index 0000000000..f236392424 --- /dev/null +++ b/config/src/test/java/org/springframework/security/config/annotation/sec2758/Sec2758Tests.java @@ -0,0 +1,150 @@ +/* + * 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.annotation.sec2758; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.annotation.Bean; +import org.springframework.core.PriorityOrdered; +import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource; +import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +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.web.access.expression.DefaultWebSecurityExpressionHandler; +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 javax.annotation.security.RolesAllowed; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Josh Cummings + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SecurityTestExecutionListeners +public class Sec2758Tests { + + @Rule + public final SpringTestRule spring = new SpringTestRule(); + + @Autowired + MockMvc mvc; + + @Autowired(required = false) + Service service; + + @WithMockUser(authorities = "CUSTOM") + @Test + public void requestWhenNullifyingRolePrefixThenPassivityRestored() throws Exception { + + this.spring.register(SecurityConfig.class).autowire(); + + this.mvc.perform(get("/")).andExpect(status().isOk()); + } + + @WithMockUser(authorities = "CUSTOM") + @Test + public void methodSecurityWhenNullifyingRolePrefixThenPassivityRestored() { + + this.spring.register(SecurityConfig.class).autowire(); + + assertThatCode(() -> service.doJsr250()) + .doesNotThrowAnyException(); + + assertThatCode(() -> service.doPreAuthorize()) + .doesNotThrowAnyException(); + } + + @EnableWebSecurity + @EnableGlobalMethodSecurity(prePostEnabled=true, jsr250Enabled = true) + static class SecurityConfig extends WebSecurityConfigurerAdapter { + + @RestController + static class RootController { + @GetMapping("/") + public String ok() { return "ok"; } + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .anyRequest().access("hasAnyRole('CUSTOM')"); + } + + @Bean + public Service service() { + return new Service(); + } + + @Bean + static DefaultRolesPrefixPostProcessor defaultRolesPrefixPostProcessor() { + return new DefaultRolesPrefixPostProcessor(); + } + + } + + static class Service { + @PreAuthorize("hasRole('CUSTOM')") + public void doPreAuthorize() {} + + @RolesAllowed("CUSTOM") + public void doJsr250() {} + } + + static class DefaultRolesPrefixPostProcessor implements BeanPostProcessor, PriorityOrdered { + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if(bean instanceof Jsr250MethodSecurityMetadataSource) { + ((Jsr250MethodSecurityMetadataSource) bean).setDefaultRolePrefix(null); + } + if(bean instanceof DefaultMethodSecurityExpressionHandler) { + ((DefaultMethodSecurityExpressionHandler) bean).setDefaultRolePrefix(null); + } + if(bean instanceof DefaultWebSecurityExpressionHandler) { + ((DefaultWebSecurityExpressionHandler) bean).setDefaultRolePrefix(null); + } + return bean; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public int getOrder() { + return PriorityOrdered.HIGHEST_PRECEDENCE; + } + } +}