Moved configuration of security interceptors with access and authentication manangers from post processing stage to bean creation stage.

This commit is contained in:
Luke Taylor 2007-12-23 16:40:29 +00:00
parent 46c99d1991
commit 5f1eea42fc
11 changed files with 227 additions and 250 deletions

View File

@ -0,0 +1,70 @@
package org.springframework.security.config;
import static org.junit.Assert.fail;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.AccessDeniedException;
import org.springframework.security.AuthenticationCredentialsNotFoundException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.annotation.BusinessService;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
/**
* @author Ben Alex
* @version $Id: InterceptMethodsBeanDefinitionDecoratorTests.java 2217 2007-10-27 00:45:30Z luke_t $
*/
public class AnnotationDrivenBeanDefinitionParserTests {
private ClassPathXmlApplicationContext appContext;
private BusinessService target;
@Before
public void loadContext() {
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/annotated-method-security.xml");
target = (BusinessService) appContext.getBean("target");
}
@After
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}
@Test
public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
try {
target.someUserMethod1();
fail("Expected AuthenticationCredentialsNotFoundException");
} catch (AuthenticationCredentialsNotFoundException expected) {
}
}
@Test
public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")});
SecurityContextHolder.getContext().setAuthentication(token);
target.someUserMethod1();
}
@Test
public void targetShouldPreventProtectedMethodInvocationWithIncorrectRole() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_SOMEOTHERROLE")});
SecurityContextHolder.getContext().setAuthentication(token);
try {
target.someAdminMethod();
fail("Expected AccessDeniedException");
} catch (AccessDeniedException expected) {
}
}
}

View File

@ -12,18 +12,21 @@ import org.springframework.security.intercept.method.aopalliance.MethodSecurityI
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Processes the top-level "annotation-driven" element.
*
*
* @author Ben Alex
* @version $Id$
*/
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
public static final String SECURITY_ANNOTATION_ATTRIBUTES_CLASS = "org.springframework.security.annotation.SecurityAnnotationAttributes";
private static final String ATT_ACCESS_MGR = "access-decision-manager";
public BeanDefinition parse(Element element, ParserContext parserContext) {
// Reflectively obtain the Annotation-based ObjectDefinitionSource.
// Reflection is used to avoid a compile-time dependency on SECURITY_ANNOTATION_ATTRIBUTES_CLASS, as this parser is in the Java 4 project whereas the dependency is in the Tiger project.
@ -34,26 +37,38 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
} catch (Exception ex) {
ReflectionUtils.handleReflectionException(ex);
}
RootBeanDefinition securityAnnotations = new RootBeanDefinition(clazz);
parserContext.getRegistry().registerBeanDefinition(BeanIds.SECURITY_ANNOTATION_ATTRIBUTES, securityAnnotations);
RootBeanDefinition methodDefinitionAttributes = new RootBeanDefinition(MethodDefinitionAttributes.class);
methodDefinitionAttributes.getPropertyValues().addPropertyValue("attributes", new RuntimeBeanReference(BeanIds.SECURITY_ANNOTATION_ATTRIBUTES));
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_ATTRIBUTES, methodDefinitionAttributes);
MethodSecurityInterceptorUtils.registerPostProcessorIfNecessary(parserContext.getRegistry());
RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class);
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
if (!StringUtils.hasText(accessManagerId)) {
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
accessManagerId = BeanIds.ACCESS_MANAGER;
}
interceptor.getPropertyValues().addPropertyValue("accessDecisionManager",
new RuntimeBeanReference(accessManagerId));
interceptor.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
interceptor.getPropertyValues().addPropertyValue("objectDefinitionSource", new RuntimeBeanReference(BeanIds.METHOD_DEFINITION_ATTRIBUTES));
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_SECURITY_INTERCEPTOR, interceptor);
RootBeanDefinition advisor = new RootBeanDefinition(MethodDefinitionSourceAdvisor.class);
advisor.getConstructorArgumentValues().addGenericArgumentValue(interceptor);
parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_DEFINITION_SOURCE_ADVISOR, advisor);
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
return null;
}
}

View File

@ -3,18 +3,18 @@ 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.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.AccessDecisionManager;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.providers.ProviderManager;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.vote.AffirmativeBased;
import org.springframework.security.vote.AuthenticatedVoter;
import org.springframework.security.vote.RoleVoter;
import org.springframework.util.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.Arrays;
import java.util.Map;
@ -27,23 +27,17 @@ import java.util.Map;
* @version $Id$
*/
public abstract class ConfigUtils {
static void registerAccessManagerIfNecessary(ConfigurableListableBeanFactory bf) {
if (bf.getBeanNamesForType(AccessDecisionManager.class).length > 0) {
return;
}
private static final Log logger = LogFactory.getLog(ConfigUtils.class);
Assert.isInstanceOf(BeanDefinitionRegistry.class, bf, "Auto-registration of default AccessManager will " +
"only work with a BeanFactory which implements BeanDefinitionRegistry");
static void registerDefaultAccessManagerIfNecessary(ParserContext parserContext) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)bf;
if (!registry.containsBeanDefinition(BeanIds.ACCESS_MANAGER)) {
if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.ACCESS_MANAGER)) {
BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class);
accessMgrBuilder.addPropertyValue("decisionVoters",
Arrays.asList(new Object[] {new RoleVoter(), new AuthenticatedVoter()}));
BeanDefinition accessMgr = accessMgrBuilder.getBeanDefinition();
registry.registerBeanDefinition(BeanIds.ACCESS_MANAGER, accessMgr);
parserContext.getRegistry().registerBeanDefinition(BeanIds.ACCESS_MANAGER, accessMgr);
}
}
@ -66,32 +60,6 @@ public abstract class ConfigUtils {
}
/**
* Supplies the BeanDefinition for an instance of AbstractSecurityInterceptor with the default
* AccessDecisionManager and AuthenticationManager.
*
* @param beanFactory
* @param securityInterceptor
*/
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));
}
static UserDetailsService getUserDetailsService(ConfigurableListableBeanFactory bf) {
Map services = bf.getBeansOfType(UserDetailsService.class);

View File

@ -73,6 +73,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_SERVLET_API_PROVISION = "servlet-api-provision";
static final String DEF_SERVLET_API_PROVISION = "true";
static final String ATT_ACCESS_MGR = "access-decision-manager";
public BeanDefinition parse(Element element, ParserContext parserContext) {
RootBeanDefinition filterChainProxy = new RootBeanDefinition(FilterChainProxy.class);
RootBeanDefinition httpScif = new RootBeanDefinition(HttpSessionContextIntegrationFilter.class);
@ -139,6 +141,19 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
filterSecurityInterceptorBuilder.addPropertyValue("objectDefinitionSource", interceptorFilterInvDefSource);
// Set up the access manager and authentication mananger references for http
String accessManagerId = element.getAttribute(ATT_ACCESS_MGR);
if (!StringUtils.hasText(accessManagerId)) {
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
accessManagerId = BeanIds.ACCESS_MANAGER;
}
filterSecurityInterceptorBuilder.addPropertyValue("accessDecisionManager",
new RuntimeBeanReference(accessManagerId));
filterSecurityInterceptorBuilder.addPropertyValue("authenticationManager",
ConfigUtils.registerProviderManagerIfNecessary(parserContext));
parseInterceptUrls(DomUtils.getChildElementsByTagName(element, "intercept-url"),
filterChainMap, interceptorFilterInvDefSource, channelFilterInvDefSource, parserContext);

View File

@ -38,12 +38,6 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
private Log logger = LogFactory.getLog(getClass());
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
ConfigUtils.registerAccessManagerIfNecessary(beanFactory);
BeanDefinition securityInterceptor =
beanFactory.getBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR);
ConfigUtils.configureSecurityInterceptor(beanFactory, securityInterceptor);
injectUserDetailsServiceIntoRememberMeServices(beanFactory);
injectAuthenticationEntryPointIntoExceptionTranslationFilter(beanFactory);
@ -55,8 +49,7 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory beanFactory) {
try {
BeanDefinition rememberMeServices =
beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
BeanDefinition rememberMeServices = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService",
ConfigUtils.getUserDetailsService(beanFactory));
} catch (NoSuchBeanDefinitionException e) {

View File

@ -5,6 +5,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.ParserContext;
@ -13,6 +14,8 @@ 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.StringUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@ -22,33 +25,48 @@ import java.util.List;
/**
* @author Luke Taylor
* @author Ben Alex
*
*
* @version $Id$
*/
public class InterceptMethodsBeanDefinitionDecorator implements BeanDefinitionDecorator {
private BeanDefinitionDecorator delegate = new InternalInterceptMethodsBeanDefinitionDecorator();
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
MethodSecurityInterceptorUtils.registerPostProcessorIfNecessary(parserContext.getRegistry());
ConfigUtils.registerProviderManagerIfNecessary(parserContext);
ConfigUtils.registerDefaultAccessManagerIfNecessary(parserContext);
return delegate.decorate(node, definition, parserContext);
}
}
/**
* This is the real class which does the work. We need acccess to the ParserContext in order to register the
* post processor,
* This is the real class which does the work. We need acccess to the ParserContext in order to do bean
* registration.
*/
class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractInterceptorDrivenBeanDefinitionDecorator {
static final String ATT_CLASS = "class";
static final String ATT_METHOD = "method";
static final String ATT_ACCESS = "access";
private Log logger = LogFactory.getLog(getClass());
private static final String ATT_ACCESS_MGR = "access-decision-manager";
private Log logger = LogFactory.getLog(getClass());
protected BeanDefinition createInterceptorDefinition(Node node) {
Element interceptMethodsElt = (Element)node;
RootBeanDefinition interceptor = new RootBeanDefinition(MethodSecurityInterceptor.class);
String accessManagerId = interceptMethodsElt.getAttribute(ATT_ACCESS_MGR);
if (!StringUtils.hasText(accessManagerId)) {
accessManagerId = BeanIds.ACCESS_MANAGER;
}
interceptor.getPropertyValues().addPropertyValue("accessDecisionManager",
new RuntimeBeanReference(accessManagerId));
interceptor.getPropertyValues().addPropertyValue("authenticationManager",
new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER));
Element beanNode = (Element)interceptMethodsElt.getParentNode();
// Get the class from the parent bean...
String targetClassName = beanNode.getAttribute(ATT_CLASS);
@ -57,7 +75,8 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto
try {
targetClass = Thread.currentThread().getContextClassLoader().loadClass(targetClassName);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Couldn't load class " + targetClassName, e);
logger.error("Couldn't load class " + targetClassName);
throw new SecurityConfigurationException("Couldn't load class " + targetClassName);
}
// Parse the included methods
@ -70,10 +89,10 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto
String accessConfig = protectmethodElt.getAttribute(ATT_ACCESS);
attributeEditor.setAsText(accessConfig);
// TODO: We want to use just the method names, but MethodDefinitionMap won't work that way.
// TODO: We want to use just the method names, but MethodDefinitionMap won't work that way.
// methodMap.addSecureMethod(targetClass, protectmethodElt.getAttribute("method"),
// (ConfigAttributeDefinition) attributeEditor.getValue());
methodMap.addSecureMethod(protectmethodElt.getAttribute(ATT_METHOD),
methodMap.addSecureMethod(protectmethodElt.getAttribute(ATT_METHOD),
(ConfigAttributeDefinition) attributeEditor.getValue());
}

View File

@ -1,53 +0,0 @@
package org.springframework.security.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
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.core.Ordered;
import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
/**
* Provides convenience methods supporting method security configuration.
*
* @author Ben Alex
* @author Luke Taylor
*
*/
abstract class MethodSecurityInterceptorUtils {
private 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;
}
}
/**
* Causes a BeanFactoryPostProcessor to be registered that will ensure all MethodSecurityInterceptor
* instances are properly configured with an AccessDecisionManager etc.
*
* @param registry to register the BeanPostProcessorWith
*/
public static void registerPostProcessorIfNecessary(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(BeanIds.INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR)) {
return;
}
registry.registerBeanDefinition(BeanIds.INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR,
new RootBeanDefinition(MethodSecurityInterceptorUtils.MethodSecurityConfigPostProcessor.class));
}
}

View File

@ -16,29 +16,21 @@ import org.junit.*;
* @version $Id$
*/
public class InterceptMethodsBeanDefinitionDecoratorTests {
private static ClassPathXmlApplicationContext appContext;
private ClassPathXmlApplicationContext appContext;
private TestBusinessBean target;
@BeforeClass
public static void loadContext() {
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/method-security.xml");
}
@AfterClass
public static void closeAppContext() {
if (appContext != null) {
appContext.close();
}
}
@Before
public void setUp() {
public void loadContext() {
appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/method-security.xml");
target = (TestBusinessBean) appContext.getBean("target");
}
@After
public void clearSecurityContext() {
public void closeAppContext() {
if (appContext != null) {
appContext.close();
}
SecurityContextHolder.clearContext();
}

View File

@ -185,7 +185,7 @@
to the Contact presented as a method argument.
-->
<bean id="contactManagerSecurity" class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationManager" ref="_authenticationManager"/>
<property name="accessDecisionManager">
<ref local="businessAccessDecisionManager"/>
</property>

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--
- Application context containing business beans.
@ -9,7 +8,11 @@
- $Id$
-->
<beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
@ -55,12 +58,12 @@
</bean>
<bean id="contactManagerTarget" class="sample.contact.ContactManagerBackend">
<property name="contactDao">
<bean class="sample.contact.ContactDaoSpring">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
</property>
<property name="mutableAclService" ref="aclService"/>
<property name="contactDao">
<bean class="sample.contact.ContactDaoSpring">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
</property>
<property name="mutableAclService" ref="aclService"/>
</bean>
</beans>

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--
- Application context containing authentication, channel
- security and web URI beans.
@ -10,84 +8,55 @@
- $Id: applicationContext-acegi-security.xml 1425 2006-04-28 06:43:50Z benalex $
-->
<beans>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- ======================== FILTER CHAIN ======================= -->
<!-- if you wish to use channel security, add "channelProcessingFilter," in front
of "httpSessionContextIntegrationFilter" in the list below -->
<http auto-config="true" realm="Contacts Realm">
<intercept-url pattern="/index.jsp" access="ROLE_ANONYMOUS,ROLE_USER"/>
<intercept-url pattern="/hello.htm" access="ROLE_ANONYMOUS,ROLE_USER"/>
<intercept-url pattern="/switchuser.jsp" access="ROLE_SUPERVISOR"/>
<intercept-url pattern="/j_spring_security_switch_user" access="ROLE_SUPERVISOR"/>
<intercept-url pattern="/acegilogin.jsp*" access="ROLE_ANONYMOUS,ROLE_USER"/>
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/acegilogin.jsp" authentication-failure-url="/acegilogin.jsp?login_error=1"/>
<logout logout-url="/index.jsp"/>
</http>
<!--
<bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value><![CDATA[
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,switchUserProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter
]]></value>
</property>
</bean>
<!-- ======================== AUTHENTICATION ======================= -->
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>
<bean id="jdbcDaoImpl" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource"><ref bean="dataSource"/></property>
</bean>
<bean id="passwordEncoder" class="org.springframework.security.providers.encoding.Md5PasswordEncoder"/>
<bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>
<!-- <property name="userCache"><ref local="userCache"/></property> -->
<property name="passwordEncoder"><ref local="passwordEncoder"/></property>
</bean>
<!--
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
<bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="cacheManager"/>
</property>
<property name="cacheName">
<value>userCache</value>
</property>
</bean>
<bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache"><ref local="userCacheBackend"/></property>
</bean>
-->
<!-- Automatically receives AuthenticationEvent messages -->
<bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>
<bean id="basicProcessingFilter" class="org.springframework.security.ui.basicauth.BasicProcessingFilter">
<property name="authenticationManager"><ref local="authenticationManager"/></property>
<property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/></property>
</bean>
<bean id="basicProcessingFilterEntryPoint" class="org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint">
<property name="realmName"><value>Contacts Realm</value></property>
<property name="realmName" value="Contacts Realm"/>
</bean>
<bean id="anonymousProcessingFilter" class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter">
<property name="key"><value>foobar</value></property>
<property name="userAttribute"><value>anonymousUser,ROLE_ANONYMOUS</value></property>
<property name="key" value="foobar"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="anonymousAuthenticationProvider" class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key"><value>foobar</value></property>
<property name="key" value="foobar"/>
</bean>
<bean id="httpSessionContextIntegrationFilter" class="org.springframework.security.context.HttpSessionContextIntegrationFilter">
</bean>
<bean id="httpSessionContextIntegrationFilter" class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>
<bean id="rememberMeProcessingFilter" class="org.springframework.security.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager"><ref local="authenticationManager"/></property>
@ -96,15 +65,15 @@
<bean id="rememberMeServices" class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>
<property name="key"><value>springRocks</value></property>
<property name="key" value="springRocks"/>
</bean>
<bean id="rememberMeAuthenticationProvider" class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key"><value>springRocks</value></property>
<property name="key" value="springRocks"/>
</bean>
<bean id="logoutFilter" class="org.springframework.security.ui.logout.LogoutFilter">
<constructor-arg value="/index.jsp"/> <!-- URL redirected to after logout -->
<constructor-arg value="/index.jsp"/>
<constructor-arg>
<list>
<ref bean="rememberMeServices"/>
@ -115,38 +84,6 @@
<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter"/>
<!-- ===================== HTTP CHANNEL REQUIREMENTS ==================== -->
<!-- You will need to uncomment the "Acegi Channel Processing Filter"
<filter-mapping> in web.xml for the following beans to be used -->
<bean id="channelProcessingFilter" class="org.springframework.security.securechannel.ChannelProcessingFilter">
<property name="channelDecisionManager"><ref local="channelDecisionManager"/></property>
<property name="filterInvocationDefinitionSource">
<value><![CDATA[
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
\A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
\A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
\A/j_spring_security_check.*\Z=REQUIRES_SECURE_CHANNEL
\A.*\Z=REQUIRES_INSECURE_CHANNEL
]]></value>
</property>
</bean>
<bean id="channelDecisionManager" class="org.springframework.security.securechannel.ChannelDecisionManagerImpl">
<property name="channelProcessors">
<list>
<ref local="secureChannelProcessor"/>
<ref local="insecureChannelProcessor"/>
</list>
</property>
</bean>
<bean id="secureChannelProcessor" class="org.springframework.security.securechannel.SecureChannelProcessor"/>
<bean id="insecureChannelProcessor" class="org.springframework.security.securechannel.InsecureChannelProcessor"/>
<!-- ===================== HTTP REQUEST SECURITY ==================== -->
<bean id="exceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint"><ref local="authenticationProcessingFilterEntryPoint"/></property>
<property name="accessDeniedHandler">
@ -169,18 +106,6 @@
<property name="forceHttps"><value>false</value></property>
</bean>
<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>
<!-- Note the order that entries are placed against the objectDefinitionSource is critical.
The FilterSecurityInterceptor will work from the top of the list down to the FIRST pattern that matches the request URL.
Accordingly, you should place MOST SPECIFIC (ie a/b/c/d.*) expressions first, with LEAST SPECIFIC (ie a/.*) expressions last -->
<bean id="filterInvocationInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
<property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property>
@ -199,14 +124,44 @@
</property>
</bean>
-->
<authentication-provider>
<password-encoder hash="md5"/>
<jdbc-user-service data-source="dataSource"/>
</authentication-provider>
<!--
<bean id="jdbcDaoImpl" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="passwordEncoder" class="org.springframework.security.providers.encoding.Md5PasswordEncoder"/>
<bean id="daoAuthenticationProvider" class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService"><ref local="jdbcDaoImpl"/></property>
<property name="passwordEncoder"><ref local="passwordEncoder"/></property>
</bean>
-->
<!-- Automatically receives AuthenticationEvent messages -->
<b:bean id="loggerListener" class="org.springframework.security.event.authentication.LoggerListener"/>
<b:bean id="httpRequestAccessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<b:property name="allowIfAllAbstainDecisions" value="false" />
<b:property name="decisionVoters">
<b:list>
<b:ref bean="roleVoter"/>
</b:list>
</b:property>
</b:bean>
<!-- Filter used to switch the user context. Note: the switch and exit url must be secured
based on the role granted the ability to 'switch' to another user -->
<!-- In this example 'rod' has ROLE_SUPERVISOR that can switch to regular ROLE_USER(s) -->
<bean id="switchUserProcessingFilter" class="org.springframework.security.ui.switchuser.SwitchUserProcessingFilter">
<property name="userDetailsService" ref="jdbcDaoImpl" />
<property name="switchUserUrl"><value>/j_spring_security_switch_user</value></property>
<property name="exitUserUrl"><value>/j_spring_security_exit_user</value></property>
<property name="targetUrl"><value>/spring-security-sample-contacts-filter/secure/index.htm</value></property>
</bean>
<b:bean id="switchUserProcessingFilter" class="org.springframework.security.ui.switchuser.SwitchUserProcessingFilter" autowire="byType">
<b:property name="targetUrl" value="/spring-security-sample-contacts-filter/secure/index.htm"/>
</b:bean>
</beans>
</b:beans>