Remove use of autoconfig, as it was really just a conveniece for creating default access and authentication managers.

This commit is contained in:
Luke Taylor 2007-10-26 13:05:31 +00:00
parent 700de0d388
commit 1bcb62af2e
7 changed files with 159 additions and 20 deletions

View File

@ -0,0 +1,78 @@
package org.springframework.security.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.security.AccessDecisionManager;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.vote.AffirmativeBased;
import org.springframework.security.vote.AuthenticatedVoter;
import org.springframework.security.vote.RoleVoter;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.Map;
/**
* @author Luke Taylor
* @version $Id$
*/
public abstract class ConfigUtils {
public static final String DEFAULT_ACCESS_MANAGER_ID = "_accessManager";
static void registerAccessManagerIfNecessary(ConfigurableListableBeanFactory bf) {
if (bf.getBeanNamesForType(AccessDecisionManager.class).length > 0) {
return;
}
Assert.isInstanceOf(BeanDefinitionRegistry.class, bf, " Auto-registration of default AccessManager will only work " +
"with a BeanFactory which implements BeanDefinitionRegistry");
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)bf;
if (!registry.containsBeanDefinition(DEFAULT_ACCESS_MANAGER_ID)) {
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
accessMgrBuilder.addPropertyValue("decisionVoters",
Arrays.asList(new Object[] {new RoleVoter(), new AuthenticatedVoter()}));
BeanDefinition accessMgr = accessMgrBuilder.getBeanDefinition();
registry.registerBeanDefinition(DEFAULT_ACCESS_MANAGER_ID, accessMgr);
}
}
static AuthenticationManager getAuthenticationManager(ConfigurableListableBeanFactory bf) {
Map authManagers = bf.getBeansOfType(AuthenticationManager.class);
if (authManagers.size() == 0) {
throw new IllegalArgumentException("No AuthenticationManager registered. " +
"Make sure you have configured at least one AuthenticationProvider?");
} else if (authManagers.size() > 1) {
throw new IllegalArgumentException("More than one AuthenticationManager registered.");
}
AuthenticationManager accessMgr = (AuthenticationManager) authManagers.values().toArray()[0];
return accessMgr;
}
static void configureSecurityInterceptor(ConfigurableListableBeanFactory beanFactory,
BeanDefinition securityInterceptor) {
ConfigUtils.registerAccessManagerIfNecessary(beanFactory);
Map accessManagers = beanFactory.getBeansOfType(AccessDecisionManager.class);
if (accessManagers.size() > 1) {
throw new IllegalArgumentException("More than one AccessDecisionManager registered. Please specify one " +
" using the TODO attribute.");
}
AccessDecisionManager accessMgr = (AccessDecisionManager) accessManagers.values().toArray()[0];
securityInterceptor.getPropertyValues().addPropertyValue("accessDecisionManager", accessMgr);
securityInterceptor.getPropertyValues().addPropertyValue("authenticationManager",
getAuthenticationManager(beanFactory));
}
}

View File

@ -88,7 +88,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource); filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
// Again pick up auth manager // Again pick up auth manager
filterSecurityInterceptorBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE); //filterSecurityInterceptorBuilder.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"), parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"),
filterChainMap, interceptorFilterInvDefSource); filterChainMap, interceptorFilterInvDefSource);

View File

@ -8,6 +8,7 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.OrderComparator; import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.security.AccessDecisionManager;
import org.springframework.security.AuthenticationManager; import org.springframework.security.AuthenticationManager;
import org.springframework.security.context.HttpSessionContextIntegrationFilter; import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.ui.AuthenticationEntryPoint; import org.springframework.security.ui.AuthenticationEntryPoint;
@ -15,7 +16,11 @@ import org.springframework.security.util.FilterChainProxy;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import javax.servlet.Filter; import javax.servlet.Filter;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/** /**
* Responsible for tying up the HTTP security configuration - building ordered filter stack and linking up * Responsible for tying up the HTTP security configuration - building ordered filter stack and linking up
@ -26,18 +31,29 @@ import java.util.*;
*/ */
public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered { public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
private Log logger = LogFactory.getLog(getClass()); private Log logger = LogFactory.getLog(getClass());
private AuthenticationManager authManager;
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
HttpSessionContextIntegrationFilter httpSCIF = (HttpSessionContextIntegrationFilter) HttpSessionContextIntegrationFilter httpSCIF = (HttpSessionContextIntegrationFilter)
beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_HTTP_SESSION_FILTER_ID); beanFactory.getBean(HttpSecurityBeanDefinitionParser.DEFAULT_HTTP_SESSION_FILTER_ID);
AuthenticationManager authManager = authManager = ConfigUtils.getAuthenticationManager(beanFactory);
(AuthenticationManager) getBeanOfType(AuthenticationManager.class, beanFactory);
configureAuthenticationEntryPoint(beanFactory); configureAuthenticationEntryPoint(beanFactory);
configureFilterSecurityInterceptor(beanFactory);
configureFilterChain(beanFactory); configureFilterChain(beanFactory);
} }
private void configureFilterSecurityInterceptor(ConfigurableListableBeanFactory beanFactory) {
ConfigUtils.registerAccessManagerIfNecessary(beanFactory);
BeanDefinition securityInterceptor =
beanFactory.getBeanDefinition(HttpSecurityBeanDefinitionParser.DEFAULT_FILTER_SECURITY_INTERCEPTOR_ID);
ConfigUtils.configureSecurityInterceptor(beanFactory, securityInterceptor);
}
/** /**
* Selects the entry point that should be used in ExceptionTranslationFilter. Strategy is * Selects the entry point that should be used in ExceptionTranslationFilter. Strategy is
* *
@ -127,6 +143,6 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
} }
public int getOrder() { public int getOrder() {
return 0; return HIGHEST_PRECEDENCE;
} }
} }

View File

@ -1,24 +1,78 @@
package org.springframework.security.config; package org.springframework.security.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator; import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor; import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.security.intercept.method.MethodDefinitionMap; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.ConfigAttributeEditor; import org.springframework.core.Ordered;
import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.ConfigAttributeEditor;
import org.springframework.security.intercept.method.MethodDefinitionMap;
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Node;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.util.List;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
/** /**
* @author Luke Taylor * @author Luke Taylor
* @version $Id$ * @version $Id$
*/ */
public class InterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator { public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator {
private static final String POST_PROCESSOR_ID = "_interceptMethodsBeanfactoryPP";
private BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator();
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
registerPostProcessorIfNecessary(parserContext.getRegistry());
return delegate.decorate(node, definition, parserContext);
}
private void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(POST_PROCESSOR_ID)) {
return;
}
registry.registerBeanDefinition(POST_PROCESSOR_ID,
new RootBeanDefinition(MethodSecurityConfigPostProcessor.class));
}
public static class MethodSecurityConfigPostProcessor implements BeanFactoryPostProcessor, Ordered {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] interceptors = beanFactory.getBeanNamesForType(MethodSecurityInterceptor.class);
for (int i=0; i < interceptors.length; i++) {
BeanDefinition interceptor = beanFactory.getBeanDefinition(interceptors[i]);
ConfigUtils.configureSecurityInterceptor(beanFactory, interceptor);
}
}
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}
}
/**
* This is the real class which does the work. We need acccess to the ParserContext in order to register the
* post processor,
*/
class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
private Log logger = LogFactory.getLog(getClass());
protected BeanDefinition createInterceptorDefinition(Node node) { protected BeanDefinition createInterceptorDefinition(Node node) {
Element interceptMethodsElt = (Element)node; Element interceptMethodsElt = (Element)node;
RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class); RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class);
@ -53,8 +107,6 @@ public class InterceptMethodsBeanDefinitionDecorator extends AbstractInterceptor
interceptor.getPropertyValues().addPropertyValue("objectDefinitionSource", methodMap); interceptor.getPropertyValues().addPropertyValue("objectDefinitionSource", methodMap);
interceptor.setAutowireMode(RootBeanDefinition.AUTOWIRE_BY_TYPE);
return interceptor; return interceptor;
} }
} }

View File

@ -15,7 +15,6 @@ public class SecurityNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("http", new HttpSecurityBeanDefinitionParser()); registerBeanDefinitionParser("http", new HttpSecurityBeanDefinitionParser());
registerBeanDefinitionParser("user-service", new UserServiceBeanDefinitionParser()); registerBeanDefinitionParser("user-service", new UserServiceBeanDefinitionParser());
registerBeanDefinitionParser("authentication-provider", new AuthenticationProviderBeanDefinitionParser()); registerBeanDefinitionParser("authentication-provider", new AuthenticationProviderBeanDefinitionParser());
registerBeanDefinitionParser("autoconfig", new AutoConfigBeanDefinitionParser());
registerBeanDefinitionDecorator("intercept-methods", new InterceptMethodsBeanDefinitionDecorator()); registerBeanDefinitionDecorator("intercept-methods", new InterceptMethodsBeanDefinitionDecorator());
registerBeanDefinitionDecorator("filter-chain-map", new FilterChainMapBeanDefinitionDecorator()); registerBeanDefinitionDecorator("filter-chain-map", new FilterChainMapBeanDefinitionDecorator());
} }

View File

@ -6,8 +6,6 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd"> http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<security:autoconfig />
<security:http createSession="ifRequired" pathType="ant" lowerCaseComparisons="true"> <security:http createSession="ifRequired" pathType="ant" lowerCaseComparisons="true">
<security:intercept-url pattern="/unprotected" filters="none"/> <security:intercept-url pattern="/unprotected" filters="none"/>
<security:intercept-url pattern="/somepath" access="ROLE_SPECIAL,ROLE_USER" /> <security:intercept-url pattern="/somepath" access="ROLE_SPECIAL,ROLE_USER" />
@ -23,12 +21,10 @@ http://www.springframework.org/schema/security http://www.springframework.org/sc
<security:http-basic realm="NamespaceTestRealm" /> <security:http-basic realm="NamespaceTestRealm" />
</security:http> </security:http>
<security:authentication-provider> <security:authentication-provider>
<security:user-service> <security:user-service>
<security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" /> <security:user name="bob" password="bobspassword" authorities="ROLE_A,ROLE_B" />
<security:user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" /> <security:user name="bill" password="billspassword" authorities="ROLE_A,ROLE_B,AUTH_OTHER" />
</security:user-service> </security:user-service>
</security:authentication-provider> </security:authentication-provider>
</beans> </beans>

View File

@ -6,8 +6,6 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd"> http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<security:autoconfig />
<bean id="target" class="org.springframework.security.config.TestBusinessBeanImpl"> <bean id="target" class="org.springframework.security.config.TestBusinessBeanImpl">
<!-- This will add a security interceptor to the bean --> <!-- This will add a security interceptor to the bean -->
<security:intercept-methods> <security:intercept-methods>