浏览代码

Fix @EnableGlobalAuthentication & method seucrity on @Configuration class

Fixes gh-3934
Rob Winch 9 年之前
父节点
当前提交
477573b3bc

+ 32 - 4
config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java

@@ -22,6 +22,8 @@ import java.util.Map;
 import org.aopalliance.intercept.MethodInterceptor;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.factory.SmartInitializingSingleton;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AdviceMode;
@@ -76,7 +78,8 @@ import org.springframework.util.Assert;
  * @see EnableGlobalMethodSecurity
  */
 @Configuration
-public class GlobalMethodSecurityConfiguration implements ImportAware {
+public class GlobalMethodSecurityConfiguration
+		implements ImportAware, SmartInitializingSingleton {
 	private static final Log logger = LogFactory
 			.getLog(GlobalMethodSecurityConfiguration.class);
 	private ObjectPostProcessor<Object> objectPostProcessor = new ObjectPostProcessor<Object>() {
@@ -94,6 +97,7 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
 	private ApplicationContext context;
 	private MethodSecurityExpressionHandler expressionHandler;
 	private Jsr250MethodSecurityMetadataSource jsr250MethodSecurityMetadataSource;
+	private MethodSecurityInterceptor methodSecurityInterceptor;
 
 	/**
 	 * Creates the default MethodInterceptor which is a MethodSecurityInterceptor using
@@ -117,18 +121,42 @@ public class GlobalMethodSecurityConfiguration implements ImportAware {
 	 */
 	@Bean
 	public MethodInterceptor methodSecurityInterceptor() throws Exception {
-		MethodSecurityInterceptor methodSecurityInterceptor = isAspectJ() ? new AspectJMethodSecurityInterceptor()
+		this.methodSecurityInterceptor = isAspectJ()
+				? new AspectJMethodSecurityInterceptor()
 				: new MethodSecurityInterceptor();
 		methodSecurityInterceptor.setAccessDecisionManager(accessDecisionManager());
 		methodSecurityInterceptor.setAfterInvocationManager(afterInvocationManager());
-		methodSecurityInterceptor.setAuthenticationManager(authenticationManager());
 		methodSecurityInterceptor
 				.setSecurityMetadataSource(methodSecurityMetadataSource());
 		RunAsManager runAsManager = runAsManager();
 		if (runAsManager != null) {
 			methodSecurityInterceptor.setRunAsManager(runAsManager);
 		}
-		return methodSecurityInterceptor;
+
+		return this.methodSecurityInterceptor;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.springframework.beans.factory.SmartInitializingSingleton#
+	 * afterSingletonsInstantiated()
+	 */
+	@Override
+	public void afterSingletonsInstantiated() {
+		try {
+			initializeMethodSecurityInterceptor();
+		}
+		catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private void initializeMethodSecurityInterceptor() throws Exception {
+		if(this.methodSecurityInterceptor == null) {
+			return;
+		}
+		this.methodSecurityInterceptor.setAuthenticationManager(authenticationManager());
 	}
 
 	/**

+ 30 - 0
config/src/test/groovy/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.groovy

@@ -23,6 +23,7 @@ import org.springframework.context.annotation.Import
 import org.springframework.core.Ordered
 import org.springframework.core.annotation.Order
 import org.springframework.security.access.annotation.Secured
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.authentication.AuthenticationManager
 import org.springframework.security.authentication.AuthenticationProvider
 import org.springframework.security.authentication.TestingAuthenticationToken
@@ -485,4 +486,33 @@ class AuthenticationConfigurationTests extends BaseSpringSpec {
 			UDS
 		}
 	}
+
+	def 'EnableGlobalMethodSecurity configuration uses PreAuthorize does not cause BeanCurrentlyInCreationException'() {
+		when:
+		loadConfig(UsesPreAuthorizeMethodSecurityConfig,AuthenticationManagerBeanConfig)
+		then:
+		noExceptionThrown()
+	}
+
+	@Configuration
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	static class UsesPreAuthorizeMethodSecurityConfig {
+		@PreAuthorize("denyAll")
+		void run() {}
+	}
+
+
+	def 'EnableGlobalMethodSecurity uses method security service'() {
+		when:
+		loadConfig(ServicesConfig,UsesPreAuthorizeMethodSecurityConfig,AuthenticationManagerBeanConfig)
+		then:
+		noExceptionThrown()
+	}
+
+	@Configuration
+	@EnableGlobalMethodSecurity(securedEnabled = true)
+	static class UsesServiceMethodSecurityConfig {
+		@Autowired
+		Service service
+	}
 }