Browse Source

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

Luke Taylor 17 năm trước cách đây
mục cha
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>