diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java index 9e3d7e0c34..2faafc63ac 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java @@ -39,6 +39,7 @@ import org.springframework.core.type.AnnotationMetadata; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.AfterInvocationProvider; +import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.access.annotation.Jsr250MethodSecurityMetadataSource; import org.springframework.security.access.annotation.Jsr250Voter; import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource; @@ -361,6 +362,14 @@ public class GlobalMethodSecurityConfiguration implements ImportAware { this.defaultMethodExpressionHandler = objectPostProcessor.postProcess(defaultMethodExpressionHandler); } + @Autowired(required = false) + public void setPermissionEvaluator(List permissionEvaluators) { + if(permissionEvaluators.size() != 1) { + logger.debug("Not autwiring PermissionEvaluator since size != 1. Got " + permissionEvaluators); + } + this.defaultMethodExpressionHandler.setPermissionEvaluator(permissionEvaluators.get(0)); + } + @SuppressWarnings("unchecked") private T lazyBean(Class interfaceName) { LazyInitTargetSource lazyTargetSource = new LazyInitTargetSource(); diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy index 071177ddd3..c17105185b 100644 --- a/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy +++ b/config/src/test/groovy/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.groovy @@ -24,6 +24,7 @@ import org.springframework.context.ApplicationListener 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 @@ -32,7 +33,6 @@ import org.springframework.security.authentication.DefaultAuthenticationEventPub import org.springframework.security.authentication.TestingAuthenticationToken import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.authentication.event.AuthenticationSuccessEvent -import org.springframework.security.config.MockAfterInvocationProvider; import org.springframework.security.config.annotation.BaseSpringSpec import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.core.Authentication @@ -199,4 +199,81 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec { 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) + } + + @Configuration + @EnableGlobalMethodSecurity(prePostEnabled = true) + public static class AutowirePermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration { + static PermissionEvaluator PE + + @Override + protected void registerAuthentication(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() + } + + @Configuration + @EnableGlobalMethodSecurity(prePostEnabled = true) + public static class MultiPermissionEvaluatorConfig extends GlobalMethodSecurityConfiguration { + static PermissionEvaluator PE + + @Override + protected void registerAuthentication(AuthenticationManagerBuilder auth) + throws Exception { + auth + .inMemoryAuthentication() + } + + @Bean + public PermissionEvaluator pe() { + PE + } + + @Bean + public PermissionEvaluator pe2() { + PE + } + + @Bean + public MethodSecurityService service() { + new MethodSecurityServiceImpl() + } + } }