SEC-3045: Conditionally add MethodSecurityMetadataSourceAdvisor

This commit is contained in:
Rob Winch 2015-07-17 15:16:09 -05:00
parent a3df41b380
commit 9654df2cc3
4 changed files with 104 additions and 21 deletions

View File

@ -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.

View File

@ -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) {

View File

@ -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());
}
}

View File

@ -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()
}
}
}