فهرست منبع

SEC-3045: Conditionally add MethodSecurityMetadataSourceAdvisor

Rob Winch 10 سال پیش
والد
کامیت
9654df2cc3

+ 5 - 19
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.

+ 7 - 2
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<String> classNames = new ArrayList<String>(4);
+		if(isProxy) {
+			classNames.add(MethodSecurityMetadataSourceAdvisorRegistrar.class.getName());
+		}
+
 		classNames.add(autoProxyClassName);
 
 		if (!skipMethodSecurityConfiguration) {

+ 62 - 0
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<String,Object> attributes = importingClassMetadata.getAllAnnotationAttributes(EnableGlobalMethodSecurity.class.getName());
+		Integer order = (Integer) attributes.getFirst("order");
+		if(order != null) {
+			advisor.addPropertyValue("order", order);
+		}
+
+		registry.registerBeanDefinition("metaDataSourceAdvisor",
+				advisor.getBeanDefinition());
+	}
+}

+ 30 - 0
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()
+		}
+	}
 }