Przeglądaj źródła

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

Luke Taylor 17 lat temu
rodzic
commit
5f1eea42fc

+ 70 - 0
core-tiger/src/test/java/org/springframework/security/config/AnnotationDrivenBeanDefinitionParserTests.java

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

+ 24 - 9
core/src/main/java/org/springframework/security/config/AnnotationDrivenBeanDefinitionParser.java

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

+ 7 - 39
core/src/main/java/org/springframework/security/config/ConfigUtils.java

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

+ 15 - 0
core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java

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

+ 1 - 8
core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java

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

+ 27 - 8
core/src/main/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.java

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

+ 0 - 53
core/src/main/java/org/springframework/security/config/MethodSecurityInterceptorUtils.java

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

+ 6 - 14
core/src/test/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecoratorTests.java

@@ -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() {
+    @Before
+    public void loadContext() {
         appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/method-security.xml");
+        target = (TestBusinessBean) appContext.getBean("target");
     }
 
-    @AfterClass
-    public static void closeAppContext() {
+    @After
+    public void closeAppContext() {
         if (appContext != null) {
             appContext.close();
         }
-    }
-
-    @Before
-    public void setUp() {
-        target = (TestBusinessBean) appContext.getBean("target");
-    }
-
-    @After
-    public void clearSecurityContext() {
         SecurityContextHolder.clearContext();
     }
 

+ 1 - 1
samples/contacts/src/main/resources/applicationContext-common-authorization.xml

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

+ 11 - 8
samples/contacts/src/main/resources/applicationContext-common-business.xml

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

+ 64 - 109
samples/contacts/src/main/webapp/WEB-INF/applicationContext-acegi-security.xml

@@ -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">
+
+
+    <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"/>
 
-   <!-- ======================== FILTER CHAIN ======================= -->
+        <form-login login-page="/acegilogin.jsp" authentication-failure-url="/acegilogin.jsp?login_error=1"/>
+        <logout logout-url="/index.jsp"/>
+    </http>
 
-	<!--  if you wish to use channel security, add "channelProcessingFilter," in front
-	      of "httpSessionContextIntegrationFilter" in the list below -->
+<!--
 	<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>