GlobalMethodSecurityConfigurationTests groovy->java

Issue: gh-4939
This commit is contained in:
Rob Winch 2018-02-12 16:28:12 -06:00
parent 6c52eb6ee1
commit 6af1ac08db
2 changed files with 484 additions and 518 deletions

View File

@ -1,518 +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.method.configuration
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl
import java.lang.reflect.Proxy
import org.springframework.beans.BeansException
import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter
import org.springframework.security.config.annotation.method.configuration.NamespaceGlobalMethodSecurityTests.BaseMethodConfig
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import javax.sql.DataSource
import org.aopalliance.intercept.MethodInterceptor
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationListener
import org.springframework.context.annotation.AdviceMode
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.access.AccessDeniedException
import org.springframework.security.access.PermissionEvaluator
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.AuthenticationTrustResolver
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher
import org.springframework.security.authentication.TestingAuthenticationToken
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.event.AuthenticationSuccessEvent
import org.springframework.security.config.annotation.BaseSpringSpec
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.method.TestPermissionEvaluator;
import org.springframework.security.core.Authentication
import org.springframework.security.core.authority.AuthorityUtils
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
*
* @author Rob Winch
*/
public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec {
def "messages set when using GlobalMethodSecurityConfiguration"() {
when:
loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
then:
authenticationManager.messages.messageSource instanceof ApplicationContext
}
def "AuthenticationEventPublisher is registered GlobalMethodSecurityConfiguration"() {
when:
loadConfig(InMemoryAuthWithGlobalMethodSecurityConfig)
then:
authenticationManager.eventPublisher instanceof DefaultAuthenticationEventPublisher
when:
Authentication auth = new UsernamePasswordAuthenticationToken("user",null,AuthorityUtils.createAuthorityList("ROLE_USER"))
authenticationManager.eventPublisher.publishAuthenticationSuccess(auth)
then:
InMemoryAuthWithGlobalMethodSecurityConfig.EVENT.authentication == auth
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration implements ApplicationListener<AuthenticationSuccessEvent> {
static AuthenticationSuccessEvent EVENT
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent e) {
EVENT = e
}
}
AuthenticationManager getAuthenticationManager() {
context.getBean(MethodInterceptor).authenticationManager
}
def "AuthenticationTrustResolver autowires"() {
setup:
CustomTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
when:
loadConfig(CustomTrustResolverConfig)
def preAdviceVoter = context.getBean(MethodInterceptor).accessDecisionManager.decisionVoters.find { it instanceof PreInvocationAuthorizationAdviceVoter}
then:
preAdviceVoter.preAdvice.expressionHandler.trustResolver == CustomTrustResolverConfig.TR
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class CustomTrustResolverConfig extends GlobalMethodSecurityConfiguration {
static AuthenticationTrustResolver TR
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public AuthenticationTrustResolver tr() {
return TR
}
}
def "SEC-2301: DefaultWebSecurityExpressionHandler has BeanResolver set"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(ExpressionHandlerHasBeanResolverSetConfig)
def service = context.getBean(ServiceImpl)
when: "service with bean reference on PreAuthorize invoked"
service.message()
then: "properly throws AccessDeniedException"
thrown(AccessDeniedException)
when: "service with bean reference on PreAuthorize invoked"
context.getBean(CustomAuthzService).grantAccess = true
service.message()
then: "grants access too"
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
static class ExpressionHandlerHasBeanResolverSetConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public ServiceImpl service() {
return new ServiceImpl()
}
@Bean
public CustomAuthzService authz() {
return new CustomAuthzService()
}
}
static class ServiceImpl {
@PreAuthorize("@authz.authorize()")
public String message() {
null
}
}
static class CustomAuthzService {
boolean grantAccess
public boolean authorize() {
grantAccess
}
}
def "Method Security supports annotations on interface parameter names"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(MethodSecurityServiceConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when: "service with annotated argument"
service.postAnnotation('deny')
then: "properly throws AccessDeniedException"
thrown(AccessDeniedException)
when: "service with annotated argument"
service.postAnnotation('grant')
then: "properly throws AccessDeniedException"
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class MethodSecurityServiceConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "GlobalMethodSecurityConfiguration autowires PermissionEvaluator"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
PermissionEvaluator evaluator = Mock()
AutowirePermissionEvaluatorConfig.PE = evaluator
loadConfig(AutowirePermissionEvaluatorConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.hasPermission("something")
then:
1 * evaluator.hasPermission(_, "something", "read") >> true
when:
service.hasPermission("something")
then:
1 * evaluator.hasPermission(_, "something", "read") >> false
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
static PermissionEvaluator PE
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public PermissionEvaluator pe() {
PE
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "GlobalMethodSecurityConfiguration does not failw with multiple PermissionEvaluator"() {
when:
loadConfig(MultiPermissionEvaluatorConfig)
then:
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration {
static PermissionEvaluator PE = new TestPermissionEvaluator()
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public PermissionEvaluator pe() {
PE
}
@Bean
public PermissionEvaluator pe2() {
PE
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "SEC-2425: EnableGlobalMethodSecurity works on superclass"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(ParentConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
}
static class ChildConfig extends ParentConfig {}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class ParentConfig {
@Autowired
protected void configurGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "SEC-2479: Support AuthenticationManager in parent"() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
loadConfig(Sec2479ParentConfig)
def child = new AnnotationConfigApplicationContext()
child.register(Sec2479ChildConfig)
child.parent = context
child.refresh()
MethodSecurityService service = child.getBean(MethodSecurityService)
when:
service.preAuthorize()
then:
thrown(AccessDeniedException)
cleanup:
child?.close()
}
@Configuration
static class Sec2479ParentConfig {
static AuthenticationManager AM
@Bean
public AuthenticationManager am() {
AM
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2479ChildConfig {
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
}
def "SEC-2815: @EnableGlobalMethodSecurity does not trigger eager initialization of Beans in GlobalAuthenticationConfigurer"() {
setup:
Sec2815Config.dataSource = Mock(DataSource)
when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
loadConfig(Sec2815Config)
then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
context.getBean(MockBeanPostProcessor).beforeInit['dataSource']
context.getBean(MockBeanPostProcessor).afterInit['dataSource']
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2815Config {
static DataSource dataSource;
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
@Bean
public MockBeanPostProcessor mockBeanPostProcessor() {
new MockBeanPostProcessor()
}
@Bean
public DataSource dataSource() {
dataSource
}
@Configuration
static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
@Autowired
DataSource dataSource
@Override
void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
}
}
}
static class MockBeanPostProcessor implements BeanPostProcessor {
Map<String,Object> beforeInit = new HashMap<String,Object>()
Map<String,Object> afterInit = new HashMap<String,Object>()
@Override
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
beforeInit[beanName] = bean
bean
}
@Override
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
afterInit[beanName] = bean
bean
}
}
def "SEC-3045: Global Security proxies security"() {
setup:
when: 'load a Configuration that uses a Bean (DataSource) in a GlobalAuthenticationConfigurerAdapter'
loadConfig(Sec3005Config)
MethodSecurityService service = context.getBean(MethodSecurityService)
then: 'The Bean (DataSource) is still properly post processed with all BeanPostProcessor'
!Proxy.isProxyClass(service.getClass())
}
@EnableGlobalMethodSecurity(prePostEnabled = true, mode= AdviceMode.ASPECTJ)
@EnableTransactionManagement
static class Sec3005Config {
static DataSource dataSource;
@Bean
public MethodSecurityService service() {
new MethodSecurityServiceImpl()
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
}
}
// gh-3797
def preAuthorizeBeanSpel() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
context = new AnnotationConfigApplicationContext(PreAuthorizeBeanSpelConfig)
BeanSpelService service = context.getBean(BeanSpelService)
when:
service.run(true)
then:
noExceptionThrown()
when:
service.run(false)
then:
thrown(AccessDeniedException)
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class PreAuthorizeBeanSpelConfig extends BaseMethodConfig {
@Bean
BeanSpelService service() {
return new BeanSpelService();
}
@Bean
BeanSpelSecurity security() {
return new BeanSpelSecurity();
}
}
static class BeanSpelService {
@PreAuthorize("@security.check(#arg)")
void run(boolean arg) {}
}
static class BeanSpelSecurity {
public boolean check(boolean arg) {
return arg;
}
}
// gh-3394
def roleHierarchy() {
setup:
SecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "password","ROLE_USER"))
context = new AnnotationConfigApplicationContext(RoleHierarchyConfig)
MethodSecurityService service = context.getBean(MethodSecurityService)
when:
service.preAuthorizeAdmin()
then:
noExceptionThrown()
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class RoleHierarchyConfig extends BaseMethodConfig {
@Bean
RoleHierarchy roleHierarchy() {
return new RoleHierarchyImpl(hierarchy:"ROLE_USER > ROLE_ADMIN")
}
}
def "GrantedAuthorityDefaults autowires"() {
when:
loadConfig(CustomGrantedAuthorityConfig)
def preAdviceVoter = context.getBean(MethodInterceptor).accessDecisionManager.decisionVoters.find { it instanceof PreInvocationAuthorizationAdviceVoter}
then:
preAdviceVoter.preAdvice.expressionHandler.defaultRolePrefix == "ROLE:"
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class CustomGrantedAuthorityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
}
@Bean
public GrantedAuthorityDefaults ga() {
return new GrantedAuthorityDefaults("ROLE:")
}
}
}

View File

@ -0,0 +1,484 @@
/*
* 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.method.configuration;
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.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.config.MockEventListener;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.core.AuthenticationException;
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.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import javax.sql.DataSource;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
*
* @author Rob Winch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SecurityTestExecutionListeners
public class GlobalMethodSecurityConfigurationTests {
@Rule
public final SpringTestRule spring = new SpringTestRule();
@Autowired(required = false)
private MethodSecurityService service;
private AuthenticationManager authenticationManager;
@Autowired
public void setMethodInterceptor(MethodSecurityInterceptor interceptor) {
this.authenticationManager = interceptor.getAuthenticationManager();
}
@Autowired(required = false)
MockEventListener<AbstractAuthenticationEvent> events;
@Test
public void methodSecurityAuthenticationManagerPublishesEvent() {
this.spring.register(InMemoryAuthWithGlobalMethodSecurityConfig.class).autowire();
try {
this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("foo", "bar"));
} catch(AuthenticationException e) {}
assertThat(this.events.getEvents()).extracting(Object::getClass).containsOnly((Class) AuthenticationFailureBadCredentialsEvent.class);
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class InMemoryAuthWithGlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication();
}
@Bean
public MockEventListener<AbstractAuthenticationEvent> listener() {
return new MockEventListener<AbstractAuthenticationEvent>() {};
}
}
@Test
@WithMockUser
public void methodSecurityWhenAuthenticationTrustResolverIsBeanThenAutowires() {
this.spring.register(CustomTrustResolverConfig.class).autowire();
AuthenticationTrustResolver trustResolver = this.spring.getContext().getBean(AuthenticationTrustResolver.class);
when(trustResolver.isAnonymous(any())).thenReturn(true, false);
assertThatThrownBy(() -> this.service.preAuthorizeNotAnonymous())
.isInstanceOf(AccessDeniedException.class);
this.service.preAuthorizeNotAnonymous();
verify(trustResolver, atLeastOnce()).isAnonymous(any());
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class CustomTrustResolverConfig {
@Bean
public AuthenticationTrustResolver trustResolver() {
return mock(AuthenticationTrustResolver.class);
}
@Bean
public MethodSecurityServiceImpl service() {
return new MethodSecurityServiceImpl();
}
}
// SEC-2301
@Test
@WithMockUser
public void defaultWebSecurityExpressionHandlerHasBeanResolverSet() {
this.spring.register(ExpressionHandlerHasBeanResolverSetConfig.class).autowire();
Authz authz = this.spring.getContext().getBean(Authz.class);
assertThatThrownBy(() -> this.service.preAuthorizeBean(false))
.isInstanceOf(AccessDeniedException.class);
this.service.preAuthorizeBean(true);
}
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
static class ExpressionHandlerHasBeanResolverSetConfig {
@Bean
public MethodSecurityServiceImpl service() {
return new MethodSecurityServiceImpl();
}
@Bean
public Authz authz() {
return new Authz();
}
}
@Test
@WithMockUser
public void methodSecuritySupportsAnnotaitonsOnInterfaceParamerNames() {
this.spring.register(MethodSecurityServiceConfig.class).autowire();
assertThatThrownBy(() -> this.service.postAnnotation("deny"))
.isInstanceOf(AccessDeniedException.class);
this.service.postAnnotation("grant");
// no exception
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class MethodSecurityServiceConfig {
@Bean
public MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
}
@Test
@WithMockUser
public void globalMethodSecurityConfigurationAutowiresPermissionEvaluator() {
this.spring.register(AutowirePermissionEvaluatorConfig.class).autowire();
PermissionEvaluator permission = this.spring.getContext().getBean(PermissionEvaluator.class);
when(permission.hasPermission(any(), eq("something"), eq("read"))).thenReturn(true, false);
this.service.hasPermission("something");
// no exception
assertThatThrownBy(() -> this.service.hasPermission("something"))
.isInstanceOf(AccessDeniedException.class);
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class AutowirePermissionEvaluatorConfig {
@Bean
public PermissionEvaluator permissionEvaluator() {
return mock(PermissionEvaluator.class);
}
@Bean
public MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
}
@Test
public void multiPermissionEvaluatorConfig() throws Exception {
this.spring.register(MultiPermissionEvaluatorConfig.class).autowire();
// no exception
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class MultiPermissionEvaluatorConfig {
@Bean
public PermissionEvaluator permissionEvaluator() {
return mock(PermissionEvaluator.class);
}
@Bean
public PermissionEvaluator permissionEvaluator2() {
return mock(PermissionEvaluator.class);
}
}
// SEC-2425
@Test
@WithMockUser
public void enableGlobalMethodSecurityWorksOnSuperclass() {
this.spring.register(ChildConfig.class).autowire();
assertThatThrownBy(() -> this.service.preAuthorize())
.isInstanceOf(AccessDeniedException.class);
}
@Configuration
static class ChildConfig extends ParentConfig {}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class ParentConfig {
@Bean
public MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
}
// SEC-2479
@Test
@WithMockUser
public void supportAuthenticationManagerInParent() {
try (AnnotationConfigWebApplicationContext parent = new AnnotationConfigWebApplicationContext()) {
parent.register(Sec2479ParentConfig.class);
parent.refresh();
try (AnnotationConfigWebApplicationContext child = new AnnotationConfigWebApplicationContext()) {
child.setParent(parent);
child.register(Sec2479ChildConfig.class);
child.refresh();
this.spring.context(child).autowire();
assertThatThrownBy(() -> this.service.preAuthorize())
.isInstanceOf(AccessDeniedException.class);
}
}
}
@Configuration
static class Sec2479ParentConfig {
@Bean
public AuthenticationManager am() {
return mock(AuthenticationManager.class);
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2479ChildConfig {
@Bean
public MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
}
@Test
public void enableGlobalMethodSecurityDoesNotTriggerEagerInitializationOfBeansInGlobalAuthenticationConfigurer() {
this.spring.register(Sec2815Config.class).autowire();
MockBeanPostProcessor pp = this.spring.getContext().getBean(MockBeanPostProcessor.class);
assertThat(pp.beforeInit).containsKeys("dataSource");
assertThat(pp.afterInit).containsKeys("dataSource");
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class Sec2815Config {
@Bean
public MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
@Bean
public MockBeanPostProcessor mockBeanPostProcessor() {
return new MockBeanPostProcessor();
}
@Bean
public DataSource dataSource() {
return mock(DataSource.class);
}
@Configuration
static class AuthConfig extends GlobalAuthenticationConfigurerAdapter {
@Autowired
DataSource dataSource;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication();
}
}
}
static class MockBeanPostProcessor implements BeanPostProcessor {
Map<String,Object> beforeInit = new HashMap<String,Object>();
Map<String,Object> afterInit = new HashMap<String,Object>();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws
BeansException {
this.beforeInit.put(beanName, bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
this.afterInit.put(beanName, bean);
return bean;
}
}
// SEC-3045
@Test
public void globalSecurityProxiesSecurity() {
this.spring.register(Sec3005Config.class).autowire();
assertThat(this.service.getClass()).matches(c-> !Proxy.isProxyClass(c), "is not proxy class");
}
@EnableGlobalMethodSecurity(prePostEnabled = true, mode= AdviceMode.ASPECTJ)
@EnableTransactionManagement
static class Sec3005Config {
@Bean
public MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication();
}
}
//
// // gh-3797
// def preAuthorizeBeanSpel() {
// setup:
// SecurityContextHolder.getContext().setAuthentication(
// new TestingAuthenticationToken("user", "password","ROLE_USER"))
// context = new AnnotationConfigApplicationContext(PreAuthorizeBeanSpelConfig)
// BeanSpelService service = context.getBean(BeanSpelService)
// when:
// service.run(true)
// then:
// noExceptionThrown()
// when:
// service.run(false)
// then:
// thrown(AccessDeniedException)
// }
//
@Test
@WithMockUser
public void preAuthorizeBeanSpel() {
this.spring.register(PreAuthorizeBeanSpelConfig.class).autowire();
assertThatThrownBy(() -> this.service.preAuthorizeBean(false))
.isInstanceOf(AccessDeniedException.class);
this.service.preAuthorizeBean(true);
}
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class PreAuthorizeBeanSpelConfig {
@Bean
MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
@Bean
Authz authz() {
return new Authz();
}
}
// gh-3394
@Test
@WithMockUser
public void roleHierarchy() {
this.spring.register(RoleHierarchyConfig.class).autowire();
assertThatThrownBy(() -> this.service.preAuthorize())
.isInstanceOf(AccessDeniedException.class);
this.service.preAuthorizeAdmin();
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public static class RoleHierarchyConfig {
@Bean
MethodSecurityService service() {
return new MethodSecurityServiceImpl();
}
@Bean
RoleHierarchy roleHierarchy() {
RoleHierarchyImpl result = new RoleHierarchyImpl();
result.setHierarchy("ROLE_USER > ROLE_ADMIN");
return result;
}
}
@Test
@WithMockUser(authorities = "ROLE:USER")
public void grantedAuthorityDefaultsAutowires() {
this.spring.register(CustomGrantedAuthorityConfig.class).autowire();
CustomGrantedAuthorityConfig.CustomAuthorityService customService = this.spring.getContext().getBean(
CustomGrantedAuthorityConfig.CustomAuthorityService.class);
assertThatThrownBy(() -> this.service.preAuthorize())
.isInstanceOf(AccessDeniedException.class);
customService.customPrefixRoleUser();
// no exception
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class CustomGrantedAuthorityConfig {
@Bean
public GrantedAuthorityDefaults ga() {
return new GrantedAuthorityDefaults("ROLE:");
}
@Bean
public CustomAuthorityService service() {
return new CustomAuthorityService();
}
@Bean
public MethodSecurityServiceImpl methodSecurityService() {
return new MethodSecurityServiceImpl();
}
static class CustomAuthorityService {
@PreAuthorize("hasRole('ROLE:USER')")
public void customPrefixRoleUser() {}
}
}
}