From 9654df2cc3e0945dc6696ccf5af8e531329e9e79 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Fri, 17 Jul 2015 15:16:09 -0500 Subject: [PATCH] SEC-3045: Conditionally add MethodSecurityMetadataSourceAdvisor --- .../GlobalMethodSecurityConfiguration.java | 24 ++----- .../GlobalMethodSecuritySelector.java | 9 ++- ...ecurityMetadataSourceAdvisorRegistrar.java | 62 +++++++++++++++++++ ...balMethodSecurityConfigurationTests.groovy | 30 +++++++++ 4 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java 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 f417fd99c4..b579960a71 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -23,9 +23,11 @@ import org.aopalliance.intercept.MethodInterceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.*; +import org.springframework.context.annotation.AdviceMode; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportAware; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.type.AnnotationMetadata; @@ -45,7 +47,6 @@ import org.springframework.security.access.intercept.AfterInvocationManager; import org.springframework.security.access.intercept.AfterInvocationProviderManager; import org.springframework.security.access.intercept.RunAsManager; import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor; -import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor; import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor; import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource; import org.springframework.security.access.method.MethodSecurityMetadataSource; @@ -317,21 +318,6 @@ public class GlobalMethodSecurityConfiguration implements ImportAware { return preInvocationAdvice; } - /** - * Obtains the {@link MethodSecurityMetadataSourceAdvisor} to be used. - * - * @return - */ - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - @Bean - public MethodSecurityMetadataSourceAdvisor metaDataSourceAdvisor() { - MethodSecurityMetadataSourceAdvisor methodAdvisor = new MethodSecurityMetadataSourceAdvisor( - "methodSecurityInterceptor", methodSecurityMetadataSource(), - "methodSecurityMetadataSource"); - methodAdvisor.setOrder(order()); - return methodAdvisor; - } - /** * Obtains the attributes from {@link EnableGlobalMethodSecurity} if this class was * imported using the {@link EnableGlobalMethodSecurity} annotation. diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java index 02b5b4cb6c..96f6b926ac 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecuritySelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -54,13 +54,18 @@ final class GlobalMethodSecuritySelector implements ImportSelector { .isAssignableFrom(importingClass); AdviceMode mode = attributes.getEnum("mode"); - String autoProxyClassName = AdviceMode.PROXY == mode ? AutoProxyRegistrar.class + boolean isProxy = AdviceMode.PROXY == mode; + String autoProxyClassName = isProxy ? AutoProxyRegistrar.class .getName() : GlobalMethodSecurityAspectJAutoProxyRegistrar.class .getName(); boolean jsr250Enabled = attributes.getBoolean("jsr250Enabled"); List classNames = new ArrayList(4); + if(isProxy) { + classNames.add(MethodSecurityMetadataSourceAdvisorRegistrar.class.getName()); + } + classNames.add(autoProxyClassName); if (!skipMethodSecurityConfiguration) { diff --git a/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java new file mode 100644 index 0000000000..1e3826ddcb --- /dev/null +++ b/config/src/main/java/org/springframework/security/config/annotation/method/configuration/MethodSecurityMetadataSourceAdvisorRegistrar.java @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2015 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.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor; +import org.springframework.util.MultiValueMap; + +/** + * Creates Spring Security's MethodSecurityMetadataSourceAdvisor only when + * using proxy based method security (i.e. do not do it when using ASPECTJ). + * The conditional logic is controlled through {@link GlobalMethodSecuritySelector}. + * + * @author Rob Winch + * @since 4.0.2 + * @see GlobalMethodSecuritySelector + */ +class MethodSecurityMetadataSourceAdvisorRegistrar implements + ImportBeanDefinitionRegistrar { + + /** + * Register, escalate, and configure the AspectJ auto proxy creator based on the value + * of the @{@link EnableGlobalMethodSecurity#proxyTargetClass()} attribute on the + * importing {@code @Configuration} class. + */ + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + + BeanDefinitionBuilder advisor = BeanDefinitionBuilder + .rootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class); + advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + advisor.addConstructorArgValue("methodSecurityInterceptor"); + advisor.addConstructorArgReference("methodSecurityMetadataSource"); + advisor.addConstructorArgValue("methodSecurityMetadataSource"); + + MultiValueMap attributes = importingClassMetadata.getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName()); + Integer order = (Integer) attributes.getFirst("order"); + if(order != null) { + advisor.addPropertyValue("order", order); + } + + registry.registerBeanDefinition("metaDataSourceAdvisor", + advisor.getBeanDefinition()); + } +} \ No newline at end of file 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 15ee30e1ca..f3af6247d9 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 @@ -15,6 +15,9 @@ */ package org.springframework.security.config.annotation.method.configuration +import java.lang.reflect.Proxy; + +import org.junit.After; import org.springframework.beans.BeansException import org.springframework.beans.factory.config.BeanPostProcessor import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter @@ -29,6 +32,7 @@ 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 @@ -48,6 +52,7 @@ 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; /** * @@ -398,4 +403,29 @@ public class GlobalMethodSecurityConfigurationTests extends BaseSpringSpec { 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() + } + } }