Преглед изворни кода

SEC-629: authentication-provider doesn't support caching.
http://jira.springframework.org/browse/SEC-629. Added support for cache-ref elements on jdbc-user-service and ldap-user-service

Luke Taylor пре 17 година
родитељ
комит
1463b9769d

+ 50 - 5
core/src/main/java/org/springframework/security/config/AbstractUserDetailsServiceBeanDefinitionParser.java

@@ -1,8 +1,12 @@
 package org.springframework.security.config;
 
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.BeanDefinitionStoreException;
 import org.springframework.util.StringUtils;
 
@@ -12,16 +16,53 @@ import org.w3c.dom.Element;
  * @author Luke Taylor
  * @version $Id$
  */
-public class AbstractUserDetailsServiceBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+public abstract class AbstractUserDetailsServiceBeanDefinitionParser implements BeanDefinitionParser {
+	private static final String CACHE_REF = "cache-ref";
+	public static final String CACHING_SUFFIX = ".caching";
+	
+	/**  UserDetailsService bean Id. For use in a stateful context (i.e. in AuthenticationProviderBDP) */
+	private String id;
+	
+	protected abstract Class getBeanClass(Element element);
+	
+    protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder);	
+	
+	public BeanDefinition parse(Element element, ParserContext parserContext) {
+		BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClass(element)); 
+		
+		doParse(element, parserContext, builder);
+		
+		RootBeanDefinition userService = (RootBeanDefinition) builder.getBeanDefinition();
+		String beanId = resolveId(element, userService, parserContext);
+		
+		parserContext.getRegistry().registerBeanDefinition(beanId, userService);
+		
+		String cacheRef = element.getAttribute(CACHE_REF);
+		
+		// Register a caching version of the user service if there's a cache-ref
+		if (StringUtils.hasText(cacheRef)) {
+			BeanDefinitionBuilder cachingUSBuilder = BeanDefinitionBuilder.rootBeanDefinition(CachingUserDetailsService.class);
+			cachingUSBuilder.addConstructorArgReference(beanId);
+			
+			cachingUSBuilder.addPropertyValue("userCache", new RuntimeBeanReference(cacheRef));
+			BeanDefinition cachingUserService = cachingUSBuilder.getBeanDefinition();
+			parserContext.getRegistry().registerBeanDefinition(beanId + CACHING_SUFFIX, cachingUserService);			
+		}
 
-    protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
-        String id = super.resolveId(element, definition, parserContext);
+		id = beanId;
+		
+		return null;
+	}
+
+    private String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) 
+    		throws BeanDefinitionStoreException {
+
+        String id = element.getAttribute("id");
 
         if (StringUtils.hasText(id)) {
             return id;
         }
 
-        // If it's nested in a parent auth-provider, generate an id automatically
         if(Elements.AUTHENTICATION_PROVIDER.equals(element.getParentNode().getNodeName())) {
             return parserContext.getReaderContext().generateBeanName(definition);
         }
@@ -34,4 +75,8 @@ public class AbstractUserDetailsServiceBeanDefinitionParser extends AbstractSing
 
         return BeanIds.USER_DETAILS_SERVICE;
     }
+
+	String getId() {
+		return id;
+	}
 }

+ 81 - 28
core/src/main/java/org/springframework/security/config/AuthenticationProviderBeanDefinitionParser.java

@@ -1,14 +1,19 @@
 package org.springframework.security.config;
 
-import org.springframework.security.providers.dao.DaoAuthenticationProvider;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.PropertyValue;
 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.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.BeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.util.xml.DomUtils;
+import org.springframework.core.Ordered;
+import org.springframework.security.providers.dao.DaoAuthenticationProvider;
 import org.springframework.util.StringUtils;
-
+import org.springframework.util.xml.DomUtils;
 import org.w3c.dom.Element;
 
 /**
@@ -36,40 +41,88 @@ class AuthenticationProviderBeanDefinitionParser implements BeanDefinitionParser
             }
         }
 
-        ConfigUtils.getRegisteredProviders(parserContext).add(authProvider);
-
-        String ref = element.getAttribute(ATT_USER_DETAILS_REF);
         Element userServiceElt = DomUtils.getChildElementByTagName(element, Elements.USER_SERVICE);
         Element jdbcUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.JDBC_USER_SERVICE);
         Element ldapUserServiceElt = DomUtils.getChildElementByTagName(element, Elements.LDAP_USER_SERVICE);
 
-        if (StringUtils.hasText(ref)) {
+        // We need to register the provider to access it in the post processor to check if it has a cache
+        final String id = parserContext.getReaderContext().generateBeanName(authProvider);
+        parserContext.getRegistry().registerBeanDefinition(id, authProvider);                    
+
+        String ref = element.getAttribute(ATT_USER_DETAILS_REF);        
+        
+        if (StringUtils.hasText(ref)) {        	
             if (userServiceElt != null || jdbcUserServiceElt != null || ldapUserServiceElt != null) {
-                parserContext.getReaderContext().error("The ref attribute cannot be used in combination with child" +
+                parserContext.getReaderContext().error("The " + ATT_USER_DETAILS_REF + " attribute cannot be used in combination with child" +
                         "elements '" + Elements.USER_SERVICE + "', '" + Elements.JDBC_USER_SERVICE + "' or '" +
                         Elements.LDAP_USER_SERVICE + "'", element);
             }
-
-            authProvider.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(ref));
-
-            return null;
-        }
-
-        // Use the child elements to create the UserDetailsService
-        BeanDefinition userDetailsService = null;
-
-        if (userServiceElt != null) {
-            userDetailsService = new UserServiceBeanDefinitionParser().parse(userServiceElt, parserContext);
-        } else if (jdbcUserServiceElt != null) {
-            userDetailsService = new JdbcUserServiceBeanDefinitionParser().parse(jdbcUserServiceElt, parserContext);
-        } else if (ldapUserServiceElt != null) {
-            userDetailsService = new LdapUserServiceBeanDefinitionParser().parse(ldapUserServiceElt, parserContext);
         } else {
-            parserContext.getReaderContext().error("A user-service is required", element);
+	        // Use the child elements to create the UserDetailsService
+	        AbstractUserDetailsServiceBeanDefinitionParser parser = null;
+	        Element elt = null;
+	
+	        if (userServiceElt != null) {
+	        	elt = userServiceElt;
+	        	parser = new UserServiceBeanDefinitionParser();
+	        } else if (jdbcUserServiceElt != null) {
+	        	elt = jdbcUserServiceElt;
+	        	parser = new JdbcUserServiceBeanDefinitionParser();
+	        } else if (ldapUserServiceElt != null) {
+	        	elt = ldapUserServiceElt;
+	        	parser = new LdapUserServiceBeanDefinitionParser();
+	        } else {
+	            parserContext.getReaderContext().error("A user-service is required", element);
+	        }
+	        
+	        parser.parse(elt, parserContext);
+	        ref = parser.getId();
         }
-
-        authProvider.getPropertyValues().addPropertyValue("userDetailsService", userDetailsService);
-
+        
+        authProvider.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(ref));        
+
+        BeanDefinitionBuilder cacheResolverBldr = BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProviderCacheResolver.class);        
+        cacheResolverBldr.addConstructorArg(id);
+        cacheResolverBldr.addConstructorArg(ref);        
+        cacheResolverBldr.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+        BeanDefinition cacheResolver = cacheResolverBldr.getBeanDefinition();
+        parserContext.getRegistry().registerBeanDefinition(
+        		parserContext.getReaderContext().generateBeanName(cacheResolver), cacheResolver);
+
+        ConfigUtils.getRegisteredProviders(parserContext).add(new RuntimeBeanReference(id));        
+        
         return null;
     }
+    
+    /**
+     * Checks whether the registered user service bean has an associated cache and, if so, sets it on the 
+     * authentication provider.
+     */
+    static class AuthenticationProviderCacheResolver implements BeanFactoryPostProcessor, Ordered {
+    	private String providerId;
+    	private String userServiceId;
+    	
+		public AuthenticationProviderCacheResolver(String providerId, String userServiceId) {
+			this.providerId = providerId;
+			this.userServiceId = userServiceId;
+		}
+
+		public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+			RootBeanDefinition provider = (RootBeanDefinition) beanFactory.getBeanDefinition(providerId);
+			
+			String cachingId = userServiceId + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
+			
+			if (beanFactory.containsBeanDefinition(cachingId)) {
+				RootBeanDefinition cachingUserService = (RootBeanDefinition) beanFactory.getBeanDefinition(cachingId);
+			
+				PropertyValue userCacheProperty = cachingUserService.getPropertyValues().getPropertyValue("userCache");
+				
+				provider.getPropertyValues().addPropertyValue(userCacheProperty);
+			}
+		}
+
+		public int getOrder() {
+			return HIGHEST_PRECEDENCE;
+		}
+    }
 }

+ 44 - 0
core/src/main/java/org/springframework/security/config/CachingUserDetailsService.java

@@ -0,0 +1,44 @@
+package org.springframework.security.config;
+
+import org.springframework.security.providers.dao.UserCache;
+import org.springframework.security.providers.dao.cache.NullUserCache;
+import org.springframework.security.userdetails.UserDetailsService;
+import org.springframework.security.userdetails.UserDetails;
+import org.springframework.util.Assert;
+
+/**
+ *
+ * @author Luke Taylor
+ * @since 2.0
+ */
+class CachingUserDetailsService implements UserDetailsService {
+	private UserCache userCache = new NullUserCache();
+	private UserDetailsService delegate;
+
+	CachingUserDetailsService(UserDetailsService delegate) {
+		this.delegate = delegate;
+	}
+
+	public UserCache getUserCache() {
+		return userCache;
+	}
+
+	public void setUserCache(UserCache userCache) {
+		this.userCache = userCache;
+	}
+
+	public UserDetails loadUserByUsername(String username) {
+		UserDetails user = userCache.getUserFromCache(username);
+		
+		if (user == null) {
+			user = delegate.loadUserByUsername(username);
+		}
+		
+		Assert.notNull(user, "UserDetailsService " + delegate + " returned null for username " + username + ". " +
+				"This is an interface contract violation");
+		
+		userCache.putUserInCache(user);
+		
+		return user;
+	}
+}

+ 9 - 1
core/src/main/java/org/springframework/security/config/ConfigUtils.java

@@ -74,8 +74,16 @@ public abstract class ConfigUtils {
     }
 
 
+    /**
+     * Obtains a user details service for use in RememberMeServices etc. Will return a caching version
+     * if available so should not be used for beans which need to separate the two. 
+     */
     static UserDetailsService getUserDetailsService(ConfigurableListableBeanFactory bf) {
-        Map services = bf.getBeansOfType(UserDetailsService.class);
+        Map services = bf.getBeansOfType(CachingUserDetailsService.class);
+        
+        if (services.size() == 0) {
+        	services = bf.getBeansOfType(UserDetailsService.class);
+        }
 
         if (services.size() == 0) {
             throw new IllegalArgumentException("No UserDetailsService registered.");

+ 3 - 1
core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java

@@ -260,7 +260,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser {
         registry.registerBeanDefinition(BeanIds.FILTER_SECURITY_INTERCEPTOR, filterSecurityInterceptorBuilder.getBeanDefinition());
 
         // Register the post processor which will tie up the loose ends in the configuration once the app context has been created and all beans are available.
-        registry.registerBeanDefinition(BeanIds.HTTP_POST_PROCESSOR, new RootBeanDefinition(HttpSecurityConfigPostProcessor.class));
+        RootBeanDefinition postProcessor = new RootBeanDefinition(HttpSecurityConfigPostProcessor.class);
+        postProcessor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+        registry.registerBeanDefinition(BeanIds.HTTP_POST_PROCESSOR, postProcessor);
 
         return null;
     }

+ 42 - 9
core/src/main/java/org/springframework/security/config/HttpSecurityConfigPostProcessor.java

@@ -16,6 +16,8 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 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.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.core.OrderComparator;
 import org.springframework.core.Ordered;
 import org.springframework.security.concurrent.ConcurrentSessionFilter;
@@ -52,30 +54,46 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
         configureFilterChain(beanFactory);
     }
 
-    private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory beanFactory) {
+    private void injectUserDetailsServiceIntoRememberMeServices(ConfigurableListableBeanFactory bf) {
         try {
-            BeanDefinition rememberMeServices = beanFactory.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
+            BeanDefinition rememberMeServices = bf.getBeanDefinition(BeanIds.REMEMBER_ME_SERVICES);
             PropertyValue pv = rememberMeServices.getPropertyValues().getPropertyValue("userDetailsService");
 
             if (pv == null) {
                 rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService",
-                    ConfigUtils.getUserDetailsService(beanFactory));
+                    ConfigUtils.getUserDetailsService(bf));
+            } else {
+            	RuntimeBeanReference cachingUserService = getCachingUserService(bf, pv.getValue());
+            	
+            	if (cachingUserService != null) {
+            		rememberMeServices.getPropertyValues().addPropertyValue("userDetailsService", cachingUserService);
+            	}            	
             }
         } catch (NoSuchBeanDefinitionException e) {
             // ignore
         }
     }
 
-    private void injectUserDetailsServiceIntoX509Provider(ConfigurableListableBeanFactory beanFactory) {
+    private void injectUserDetailsServiceIntoX509Provider(ConfigurableListableBeanFactory bf) {
         try {
-            BeanDefinition x509AuthProvider = beanFactory.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
+            BeanDefinition x509AuthProvider = bf.getBeanDefinition(BeanIds.X509_AUTH_PROVIDER);
             PropertyValue pv = x509AuthProvider.getPropertyValues().getPropertyValue("preAuthenticatedUserDetailsService");
 
             if (pv == null) {
                 UserDetailsByNameServiceWrapper preAuthUserService = new UserDetailsByNameServiceWrapper();
-                preAuthUserService.setUserDetailsService(ConfigUtils.getUserDetailsService(beanFactory));
+                preAuthUserService.setUserDetailsService(ConfigUtils.getUserDetailsService(bf));
                 x509AuthProvider.getPropertyValues().addPropertyValue("preAuthenticatedUserDetailsService",
                         preAuthUserService);
+            } else {
+            	RootBeanDefinition preAuthUserService = (RootBeanDefinition) pv.getValue();
+            	Object userService = 
+            		preAuthUserService.getPropertyValues().getPropertyValue("userDetailsService").getValue();
+            	
+            	RuntimeBeanReference cachingUserService = getCachingUserService(bf, userService);
+            	
+            	if (cachingUserService != null) {
+            		preAuthUserService.getPropertyValues().addPropertyValue("userDetailsService", cachingUserService);
+            	}
             }
         } catch (NoSuchBeanDefinitionException e) {
             // ignore
@@ -94,7 +112,22 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
         } catch (NoSuchBeanDefinitionException e) {
             // ignore
         }
-    }    
+    }
+    
+    private RuntimeBeanReference getCachingUserService(ConfigurableListableBeanFactory bf, Object userServiceRef) {
+    	Assert.isInstanceOf(RuntimeBeanReference.class, userServiceRef, 
+    			"userDetailsService property value must be a RuntimeBeanReference");
+    	
+    	String id = ((RuntimeBeanReference)userServiceRef).getBeanName();
+    	// Overwrite with the caching version if available
+    	String cachingId = id + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX;
+    	
+    	if (bf.containsBeanDefinition(cachingId)) {
+    		return new RuntimeBeanReference(cachingId);
+    	}
+    	
+    	return null;
+    }
 
     /**
      * Sets the authentication manager, (and remember-me services, if required) on any instances of
@@ -148,7 +181,7 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
      * <ol>
      * <li>If only one, use that one.</li>
      * <li>If more than one, use the form login entry point (if form login is being used), then try basic</li>
-     * <li>If still null, throw an exception (for now). TODO: Examine additional beans and types and make decision</li>
+     * <li>If still null, throw an exception (for now).</li>
      * </ol>
      *
      */
@@ -257,6 +290,6 @@ public class HttpSecurityConfigPostProcessor implements BeanFactoryPostProcessor
     }
 
     public int getOrder() {
-        return HIGHEST_PRECEDENCE;
+        return HIGHEST_PRECEDENCE + 1;
     }
 }

+ 2 - 1
core/src/main/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParser.java

@@ -2,6 +2,7 @@ package org.springframework.security.config;
 
 import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.beans.factory.BeanDefinitionStoreException;
 
 import org.w3c.dom.Element;
@@ -17,7 +18,7 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
         return JdbcUserDetailsManager.class;
     }
 
-    protected void doParse(Element element, BeanDefinitionBuilder builder) {
+    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
         // TODO: Set authenticationManager property
         String dataSource = element.getAttribute(ATT_DATA_SOURCE);
         // An explicit dataSource was specified, so use it

+ 2 - 1
core/src/main/java/org/springframework/security/config/UserServiceBeanDefinitionParser.java

@@ -4,6 +4,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.PropertiesFactoryBean;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.beans.factory.BeanDefinitionStoreException;
 import org.springframework.security.userdetails.memory.InMemoryDaoImpl;
 import org.springframework.security.userdetails.memory.UserMap;
@@ -36,7 +37,7 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB
         return InMemoryDaoImpl.class;
     }
 
-    protected void doParse(Element element, BeanDefinitionBuilder builder) {
+    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
         String userProperties = element.getAttribute(ATT_PROPERTIES);
         List userElts = DomUtils.getChildElementsByTagName(element, ELT_USER);
 

+ 0 - 66
core/src/main/java/org/springframework/security/providers/UserDetailsService.java

@@ -1,66 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.providers;
-
-import org.springframework.security.AuthenticationException;
-import org.springframework.security.userdetails.UserDetails;
-
-/**
- * Populates the <code>UserDetails</code> associated with a CAS authenticated
- * user.
- *
- * <p>
- * Intended to grant authorities (roles) for providers that do not support
- * authorities/roles directly. It merely authenticates their identity.
- * As Spring Security needs to know the authorities granted to a user in
- * order to construct a valid <code>Authentication</code> object, implementations
- * of this interface will provide this information.
- * </p>
- *
- * <p>
- * A {@link UserDetails} is returned by implementations. The
- * <code>UserDetails</code> must, at minimum, contain the username and
- * <code>GrantedAuthority[]</code> objects applicable to the authenticated
- * user. Note that Spring Security ignores the password and enabled/disabled
- * status of the <code>UserDetails</code> because this is
- * authentication-related and should have been enforced by another provider server. The
- * <code>UserDetails</code> returned by implementations is stored in the
- * generated <code>AuthenticationToken</code>, so additional properties
- * such as email addresses, telephone numbers etc can easily be stored.
- * </p>
- *
- * <p>
- * Implementations should not perform any caching. They will only be called
- * when a refresh is required.
- * </p>
- *
- * @author Ben Alex
- * @author Ray Krueger
- * @version $Id$
- */
-public interface UserDetailsService {
-    /**
-     * Obtains the granted authorities for the specified user.<P>May throw any
-     * <code>AuthenticationException</code> or return <code>null</code> if the authorities are unavailable.</p>
-     *
-     * @param casUserId as obtained from the CAS validation service
-     *
-     * @return the details of the indicated user (at minimum the granted authorities and the username)
-     *
-     * @throws org.springframework.security.AuthenticationException DOCUMENT ME!
-     */
-    UserDetails getUserDetails(String casUserId)
-        throws AuthenticationException;
-}

+ 10 - 2
core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc

@@ -29,7 +29,11 @@ id =
 ref =
     ## Defines a reference to a Spring bean Id.
     attribute ref {xsd:string}
-    
+
+cache-ref =
+    ## Defines a reference to a cache for use with a UserDetailsService.
+    attribute cache-ref {xsd:string}
+
 user-service-ref =
     ## A reference to a user-service (or UserDetailsService bean) Id
     attribute user-service-ref {xsd:string}
@@ -104,6 +108,8 @@ ldap-us.attlist &=
     group-search-base-attribute?
 ldap-us.attlist &=
     group-role-attribute-attribute?
+ldap-us.attlist &=
+    cache-ref?
 
 ldap-authentication-provider =
     ## Sets up an ldap authentication provider
@@ -391,7 +397,9 @@ jdbc-user-service =
 jdbc-user-service.attlist &=
 	  ## The bean ID of the DataSource which provides the required tables.
     attribute data-source-ref {xsd:string}
-    
+jdbc-user-service.attlist &=
+    cache-ref?
+
 any-user-service = user-service | jdbc-user-service | ldap-user-service
     
 custom-filter =

+ 1188 - 2047
core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd

@@ -1,2058 +1,1199 @@
 <?xml version="1.0" encoding="utf-8"?>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-  xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified"
-  targetNamespace="http://www.springframework.org/schema/security">
-
-  <xs:attributeGroup name="hash">
-
-    <xs:attribute name="hash" use="required">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
-          strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="plaintext"/>
-
-          <xs:enumeration value="sha"/>
-
-          <xs:enumeration value="md5"/>
-
-          <xs:enumeration value="md4"/>
-
-          <xs:enumeration value="{sha}"/>
-
-          <xs:enumeration value="{ssha}"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="base64">
-
-    <xs:attribute name="base64" use="required">
-
-      <xs:annotation>
-
-        <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="path-type">
-
-    <xs:attribute name="path-type" use="required">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
-          1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
-          unspecified.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="ant"/>
-
-          <xs:enumeration value="regex"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="port">
-
-    <xs:attribute name="port" use="required" type="xs:integer">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
-          for example.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="url">
-
-    <xs:attribute name="url" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies a URL.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="id">
-
-    <xs:attribute name="id" use="required" type="xs:ID">
-
-      <xs:annotation>
-
-        <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
-          context.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="ref">
-
-    <xs:attribute name="ref" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="user-service-ref">
-
-    <xs:attribute name="user-service-ref" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="password-encoder">
-    <xs:annotation>
-
-      <xs:documentation>element which defines a password encoding strategy. Used by an
-        authentication provider to convert submitted passwords to hashed versions, for example.</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element minOccurs="0" name="salt-source">
-          <xs:complexType>
-
-            <xs:attribute name="user-property" type="xs:string">
-
-              <xs:annotation>
-
-                <xs:documentation>A property of the UserDetails object which will be used as salt by
-                  a password encoder. Typically something like "username" might be used. </xs:documentation>
-
-              </xs:annotation>
-
-            </xs:attribute>
-
-            <xs:attribute name="system-wide" type="xs:string">
-
-              <xs:annotation>
-
-                <xs:documentation>A single value that will be used as the salt for a password
-                  encoder. </xs:documentation>
-
-              </xs:annotation>
-
-            </xs:attribute>
-
-          </xs:complexType>
-        </xs:element>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:password-encoder.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="password-encoder.attlist">
-
-    <xs:attribute name="ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="hash">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
-          strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="plaintext"/>
-
-          <xs:enumeration value="sha"/>
-
-          <xs:enumeration value="md5"/>
-
-          <xs:enumeration value="md4"/>
-
-          <xs:enumeration value="{sha}"/>
-
-          <xs:enumeration value="{ssha}"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="base64">
-
-      <xs:annotation>
-
-        <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="user-property">
-
-    <xs:attribute name="user-property" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A property of the UserDetails object which will be used as salt by a
-          password encoder. Typically something like "username" might be used. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="system-wide">
-
-    <xs:attribute name="system-wide" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A single value that will be used as the salt for a password encoder. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="ldap-server">
-    <xs:annotation>
-
-      <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
-        indicates the location of a remote server. If no url is given, an embedded server will be
-        started, listening on the supplied port number. The port is optional and defaults to 33389.
-        A Spring LDAP ContextSource bean will be registered for the server with the id supplied. </xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:ldap-server.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="ldap-server.attlist">
-
-    <xs:attribute name="id" type="xs:ID">
-
-      <xs:annotation>
-
-        <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
-          context.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="url" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies a URL.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="port" type="xs:integer">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP server,
-          for example.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="manager-dn" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Username (DN) of the "manager" user identity which will be used to
-          authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will be used. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="manager-password" type="xs:string"/>
-
-    <xs:attribute name="ldif" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Explicitly specifies an ldif file resource to load into an embedded LDAP
-          server</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="root" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Optional root suffix for the embedded LDAP server. Default is
-          "dc=springframework,dc=org"</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="ldap-server-ref-attribute">
-
-    <xs:attribute name="server-ref" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
-          registered (using &lt;ldap-server&gt; with no Id), that server will be used. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="group-search-filter-attribute">
-
-    <xs:attribute name="group-search-filter" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
-          parameter is the DN of the user.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="group-search-base-attribute">
-
-    <xs:attribute name="group-search-base" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Search base for group membership searches. Defaults to "ou=groups".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="user-search-filter-attribute">
-
-    <xs:attribute name="user-search-filter" use="required" type="xs:string"/>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="user-search-base-attribute">
-
-    <xs:attribute name="user-search-base" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="group-role-attribute-attribute">
-
-    <xs:attribute name="group-role-attribute" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The LDAP attribute name which contains the role name which will be used
-          within Spring Security. Defaults to "cn".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:ldap-us.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="ldap-us.attlist">
-
-    <xs:attribute name="id" type="xs:ID">
-
-      <xs:annotation>
-
-        <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
-          context.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="server-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
-          registered (using &lt;ldap-server&gt; with no Id), that server will be used. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="user-search-filter" type="xs:string"/>
-
-    <xs:attributeGroup ref="security:user-search-base-attribute"/>
-
-    <xs:attribute name="group-search-filter" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
-          parameter is the DN of the user.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="group-search-base" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Search base for group membership searches. Defaults to "ou=groups".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="group-role-attribute" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The LDAP attribute name which contains the role name which will be used
-          within Spring Security. Defaults to "cn".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="ldap-authentication-provider">
-    <xs:annotation>
-
-      <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element minOccurs="0" ref="security:password-compare"/>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:ldap-ap.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="ldap-ap.attlist">
-
-    <xs:attribute name="server-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The optional server to use. If omitted, and a default LDAP server is
-          registered (using &lt;ldap-server&gt; with no Id), that server will be used. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attributeGroup ref="security:user-search-base-attribute"/>
-
-    <xs:attribute name="user-search-filter" type="xs:string"/>
-
-    <xs:attribute name="group-search-base" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Search base for group membership searches. Defaults to "ou=groups".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="group-search-filter" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
-          parameter is the DN of the user.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="group-role-attribute" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The LDAP attribute name which contains the role name which will be used
-          within Spring Security. Defaults to "cn".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="user-dn-pattern" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A specific pattern used to build the user's DN, for example
-          "uid={0},ou=people". The key "{0}" must be present and will be substituted with the
-          username.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="password-compare">
-    <xs:annotation>
-
-      <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation of the
-        user's password to authenticate the user</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element minOccurs="0" ref="security:password-encoder"/>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:password-compare.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="password-compare.attlist">
-
-    <xs:attribute name="password-attribute" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The attribute in the directory which contains the user password. Defaults
-          to "userPassword".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="hash">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
-          strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="plaintext"/>
-
-          <xs:enumeration value="sha"/>
-
-          <xs:enumeration value="md5"/>
-
-          <xs:enumeration value="md4"/>
-
-          <xs:enumeration value="{sha}"/>
-
-          <xs:enumeration value="{ssha}"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="intercept-methods">
-    <xs:annotation>
-
-      <xs:documentation>Can be used inside a bean definition to add a security interceptor to the
-        bean and set up access configuration attributes for the bean's methods</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element maxOccurs="unbounded" ref="security:protect"/>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:intercept-methods.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="intercept-methods.attlist">
-
-    <xs:attribute name="access-decision-manager-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created method
-          security interceptor.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="protect">
-    <xs:annotation>
-
-      <xs:documentation>Defines a protected method and the access control configuration attributes
-        that apply to it. We strongly advise you NOT to mix "protect" declarations with any services
-        provided "global-method-security".</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:protect.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="protect.attlist">
-
-    <xs:attribute name="method" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A method name</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="access" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Access configuration attributes list that applies to the method, e.g.
-          "ROLE_A,ROLE_B".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="global-method-security">
-    <xs:annotation>
-
-      <xs:documentation>Provides method security for all beans registered in the Spring application
-        context. Specifically, beans will be scanned for Spring Security annotations and/or matches
-        with the ordered list of "protect-pointcut" sub-elements. Where there is a match, the beans
-        will automatically be proxied and security authorization applied to the methods accordingly.
-        If you use and enable all three sources of method security metadata (ie "protect-pointcut"
-        declarations, @Secured and also JSR 250 security annotations), the metadata sources will be
-        queried in that order. In practical terms, this enables you to use XML to override method
-        security metadata expressed by way of @Secured annotations, with @Secured annotations
-        overriding method security metadata expressed by JSR 250 annotations. It is perfectly
-        acceptable to mix and match, with a given Java type using a combination of XML, @Secured and
-        JSR 250 to express method security metadata (albeit on different methods).</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
-          <xs:annotation>
-
-            <xs:documentation>Defines a protected pointcut and the access control configuration
-              attributes that apply to it. Every bean registered in the Spring application context
-              that provides a method that matches the pointcut will receive security authorization.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:global-method-security.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="global-method-security.attlist">
-
-    <xs:attribute name="secured-annotations">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies whether the use of Spring Security's @Secured annotations should
-          be enabled for this application context. Please ensure you have the
-          spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="disabled"/>
-
-          <xs:enumeration value="enabled"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="jsr250-annotations">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for example
-          "RolesAllowed"). This will require the javax.annotation.security classes on the classpath.
-          Defaults to "disabled".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="disabled"/>
-
-          <xs:enumeration value="enabled"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="access-decision-manager-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Optional AccessDecisionManager bean ID to override the default used for
-          method security.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="protect-pointcut.attlist">
-
-    <xs:attribute name="expression" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>An AspectJ expression, including the 'execution' keyword. For example,
-          'execution(int com.foo.TargetObject.countLength(String))' (without the quotes).</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="access" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Access configuration attributes list that applies to all methods matching
-          the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="http">
-    <xs:annotation>
-
-      <xs:documentation>Container element for HTTP security configuration</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:choice minOccurs="0" maxOccurs="unbounded">
-
-        <xs:element name="intercept-url">
-          <xs:annotation>
-
-            <xs:documentation>Specifies the access attributes and/or filter list for a particular
-              set of URLs.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:intercept-url.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element name="form-login">
-          <xs:annotation>
-
-            <xs:documentation>Sets up a form login configuration for authentication with a username
-              and password</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:form-login.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element ref="security:openid-login"/>
-
-        <xs:element name="x509">
-          <xs:annotation>
-
-            <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:x509.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element name="http-basic">
-          <xs:annotation>
-
-            <xs:documentation>Adds support for basic authentication (this is an element to permit
-              future expansion, such as supporting an "ignoreFailure" attribute)</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType/>
-        </xs:element>
-
-        <xs:element name="logout">
-          <xs:annotation>
-
-            <xs:documentation>Incorporates a logout processing filter. Most web applications require
-              a logout filter, although you may not require one if you write a controller to
-              provider similar logic.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:logout.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element name="concurrent-session-control">
-          <xs:annotation>
-
-            <xs:documentation>Adds support for concurrent session control, allowing limits to be
-              placed on the number of sessions a user can have.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:concurrent-sessions.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element name="remember-me">
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:remember-me.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element name="anonymous">
-          <xs:annotation>
-
-            <xs:documentation>Adds support for automatically granting all anonymous web requests a
-              particular principal identity and a corresponding granted authority.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:anonymous.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-        <xs:element name="port-mappings">
-          <xs:annotation>
-
-            <xs:documentation>Defines the list of mappings between http and https ports for use in
-              redirects</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:sequence>
-
-              <xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
-
-            </xs:sequence>
-
-          </xs:complexType>
-        </xs:element>
-
-      </xs:choice>
-
-      <xs:attributeGroup ref="security:http.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="http.attlist">
-
-    <xs:attribute name="auto-config">
-
-      <xs:annotation>
-
-        <xs:documentation>Automatically registers a login form, BASIC authentication, anonymous
-          authentication, logout services, remember-me and servlet-api-integration. If set to
-          "true", all of these capabilities are added (although you can still customize the
-          configuration of each by providing the respective element). If unspecified, defaults to
-          "false".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="create-session">
-
-      <xs:annotation>
-
-        <xs:documentation>Controls the eagerness with which an HTTP session is created. If not set,
-          defaults to "ifRequired".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="ifRequired"/>
-
-          <xs:enumeration value="always"/>
-
-          <xs:enumeration value="never"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="path-type">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
-          1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
-          unspecified.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="ant"/>
-
-          <xs:enumeration value="regex"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="lowercase-comparisons">
-
-      <xs:annotation>
-
-        <xs:documentation>Whether test URLs should be converted to lower case prior to comparing
-          with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="servlet-api-provision">
-
-      <xs:annotation>
-
-        <xs:documentation>Provides versions of HttpServletRequest security methods such as
-          isUserInRole() and getPrincipal() which are implemented by accessing the Spring
-          SecurityContext. Defaults to "true".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="access-decision-manager-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager
-          implementation which should be used for authorizing HTTP requests.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="realm" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Optional attribute specifying the realm name that will be used for all
-          authentication features that require a realm name (eg BASIC and Digest authentication). If
-          unspecified, defaults to "Spring Security Application".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="session-fixation-protection">
-
-      <xs:annotation>
-
-        <xs:documentation>Indicates whether an existing session should be invalidated when a user
-          authenticates and a new session started. If set to "none" no change will be made.
-          "newSession" will create a new empty session. "migrateSession" will create a new session
-          and copy the session attributes to the new session. Defaults to "migrateSession".</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="none"/>
-
-          <xs:enumeration value="newSession"/>
-
-          <xs:enumeration value="migrateSession"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="intercept-url.attlist">
-
-    <xs:attribute name="pattern" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The pattern which defines the URL path. The content will depend on the
-          type set in the containing http element, so will default to ant path syntax.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="access" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The access configuration attributes that apply for the configured path.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="method">
-
-      <xs:annotation>
-
-        <xs:documentation>The HTTP Method for which the access configuration attributes should
-          apply. If not specified, the attributes will apply to any method.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="GET"/>
-
-          <xs:enumeration value="DELETE"/>
-
-          <xs:enumeration value="HEAD"/>
-
-          <xs:enumeration value="OPTIONS"/>
-
-          <xs:enumeration value="POST"/>
-
-          <xs:enumeration value="PUT"/>
-
-          <xs:enumeration value="TRACE"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="filters">
-
-      <xs:annotation>
-
-        <xs:documentation>The filter list for the path. Currently can be set to "none" to remove a
-          path from having any filters applied. The full filter stack (consisting of all defined
-          filters, will be applied to any other paths).</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="none"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="requires-channel">
-
-      <xs:annotation>
-
-        <xs:documentation>Used to specify that a URL must be accessed over http or https</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="http"/>
-
-          <xs:enumeration value="https"/>
-
-          <xs:enumeration value="any"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="logout.attlist">
-
-    <xs:attribute name="logout-url" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies the URL that will cause a logout. Spring Security will
-          initialize a filter that responds to this particular URL. Defaults to
-          /j_spring_security_logout if unspecified.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="logout-success-url" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies the URL to display once the user has logged out. If not
-          specified, defaults to /.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="invalidate-session">
-
-      <xs:annotation>
-
-        <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is
-          generally desirable. If unspecified, defaults to true.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="form-login.attlist">
-
-    <xs:attribute name="login-processing-url" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The URL that the login form is posted to. If unspecified, it defaults to
-          /j_spring_security_check.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="default-target-url" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The URL that will be redirected to after successful authentication, if the
-          user's previous action could not be resumed. This generally happens if the user visits a
-          login page without having first requested a secured operation that triggers
-          authentication. If unspecified, defaults to the root of the application.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="login-page" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The URL for the login page. If no login URL is specified, Spring Security
-          will automatically create a login URL at /spring_security_login and a corresponding filter
-          to render that login URL when requested.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="authentication-failure-url" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The URL for the login failure page. If no login failure URL is specified,
-          Spring Security will automatically create a failure login URL at
-          /spring_security_login?login_error and a corresponding filter to render that login failure
-          URL when requested.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="openid-login">
-    <xs:annotation>
-
-      <xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:form-login.attlist"/>
-
-      <xs:attribute name="user-service-ref" type="xs:string">
-
-        <xs:annotation>
-
-          <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
-
-        </xs:annotation>
-
-      </xs:attribute>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:element name="filter-chain-map">
-    <xs:annotation>
-
-      <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a
-        FilterChainMap</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element maxOccurs="unbounded" name="filter-chain">
-          <xs:annotation>
-
-            <xs:documentation>Used within filter-chain-map to define a specific URL pattern and the
-              list of filters which apply to the URLs matching that pattern. When multiple
-              filter-chain elements are used within a filter-chain-map element, the most specific
-              patterns must be placed at the top of the list, with most general ones at the bottom.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:filter-chain.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="filter-chain-map.attlist">
-
-    <xs:attributeGroup ref="security:path-type"/>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="filter-chain.attlist">
-
-    <xs:attribute name="pattern" use="required" type="xs:string"/>
-
-    <xs:attribute name="filters" use="required" type="xs:string"/>
-
-  </xs:attributeGroup>
-
-  <xs:element name="filter-invocation-definition-source">
-    <xs:annotation>
-
-      <xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean for use
-        with a FilterSecurityInterceptor. Usually only needed if you are configuring a
-        FilterChainProxy explicitly, rather than using the &lt;http&gt; element. The
-        intercept-url elements used should only contain pattern, method and access attributes. Any
-        others will result in a configuration error. </xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element maxOccurs="unbounded" name="intercept-url">
-          <xs:annotation>
-
-            <xs:documentation>Specifies the access attributes and/or filter list for a particular
-              set of URLs.</xs:documentation>
-
-          </xs:annotation>
-          <xs:complexType>
-
-            <xs:attributeGroup ref="security:intercept-url.attlist"/>
-
-          </xs:complexType>
-        </xs:element>
-
-      </xs:sequence>
-
-      <xs:attributeGroup ref="security:fids.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="fids.attlist">
-
-    <xs:attribute name="id" type="xs:ID">
-
-      <xs:annotation>
-
-        <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
-          context.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="lowercase-comparisons">
-
-      <xs:annotation>
-
-        <xs:documentation>as for http element</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-    <xs:attribute name="path-type">
-
-      <xs:annotation>
-
-        <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
-          1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if
-          unspecified.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="ant"/>
-
-          <xs:enumeration value="regex"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-
-  <xs:attributeGroup name="concurrent-sessions.attlist">
-
-    <xs:attribute name="max-sessions" type="xs:positiveInteger"/>
-
-    <xs:attribute name="expired-url" type="xs:string"/>
-
-    <xs:attribute name="exception-if-maximum-exceeded">
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="remember-me.attlist">
-
-    <xs:attribute name="key" type="xs:string"/>
-
-    <xs:attribute name="token-repository-ref" type="xs:string"/>
-
-    <xs:attribute name="data-source-ref" type="xs:string"/>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="anonymous.attlist">
-
-    <xs:attribute name="key" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The key shared between the provider and filter. This generally does not
-          need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="username" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The username that should be assigned to the anonymous request. This allows
-          the principal to be identified, which may be important for logging and auditing. if unset,
-          defaults to "anonymousUser".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="granted-authority" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The granted authority that should be assigned to the anonymous request.
-          Commonly this is used to assign the anonymous request particular roles, which can
-          subsequently be used in authorization decisions. If unset, defaults to "ROLE_ANONYMOUS".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-
-  <xs:element name="port-mapping">
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:http-port"/>
-
-      <xs:attributeGroup ref="security:https-port"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="http-port">
-
-    <xs:attribute name="http" use="required" type="xs:integer"/>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="https-port">
-
-    <xs:attribute name="https" use="required" type="xs:integer"/>
-
-  </xs:attributeGroup>
-
-
-  <xs:attributeGroup name="x509.attlist">
-
-    <xs:attribute name="subject-principal-regex" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The regular expression used to obtain the username from the certificate's
-          subject. Defaults to matching on the common name using the pattern "CN=(.*?),".</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="user-service-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="authentication-manager">
-    <xs:annotation>
-
-      <xs:documentation>If you are using namespace configuration with Spring Security, an
-        AuthenticationManager will automatically be registered. This element simple allows you to
-        define an alias to allow you to reference the authentication-manager in your own beans. </xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:authman.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="authman.attlist">
-
-    <xs:annotation>
-
-      <xs:documentation>The alias you wish to use for the AuthenticationManager bean</xs:documentation>
-
-    </xs:annotation>
-
-    <xs:attribute name="alias" use="required" type="xs:ID"/>
-
-  </xs:attributeGroup>
-
-  <xs:element name="authentication-provider">
-    <xs:annotation>
-
-      <xs:documentation>Indicates that the contained user-service should be used as an
-        authentication source. </xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:choice minOccurs="0" maxOccurs="unbounded">
-
-        <xs:element ref="security:any-user-service"/>
-
-        <xs:element ref="security:password-encoder"/>
-
-      </xs:choice>
-
-      <xs:attributeGroup ref="security:ap.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="ap.attlist">
-
-    <xs:attribute name="user-service-ref" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="custom-authentication-provider">
-    <xs:complexType/>
-  </xs:element>
-
-  <xs:element name="user-service" substitutionGroup="security:any-user-service">
-    <xs:annotation>
-
-      <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a list of
-        "user" child elements.</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:sequence>
-
-        <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:user"/>
-
-      </xs:sequence>
-
-      <xs:attribute name="id" type="xs:ID">
-
+    xmlns:security="http://www.springframework.org/schema/security" elementFormDefault="qualified"
+    targetNamespace="http://www.springframework.org/schema/security">
+    <xs:attributeGroup name="hash">
+        <xs:attribute name="hash" use="required">
+            <xs:annotation>
+                <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
+                    strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="plaintext"/>
+                    <xs:enumeration value="sha"/>
+                    <xs:enumeration value="md5"/>
+                    <xs:enumeration value="md4"/>
+                    <xs:enumeration value="{sha}"/>
+                    <xs:enumeration value="{ssha}"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="base64">
+        <xs:attribute name="base64" use="required">
+            <xs:annotation>
+                <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="path-type">
+        <xs:attribute name="path-type" use="required">
+            <xs:annotation>
+                <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
+                    1.4-compatible regular expressions, or Apache Ant expressions). Defaults to
+                    "ant" if unspecified.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="ant"/>
+                    <xs:enumeration value="regex"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="port">
+        <xs:attribute name="port" use="required" type="xs:integer">
+            <xs:annotation>
+                <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP
+                    server, for example.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="url">
+        <xs:attribute name="url" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Specifies a URL.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="id">
+        <xs:attribute name="id" use="required" type="xs:ID">
+            <xs:annotation>
+                <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
+                    context.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="ref">
+        <xs:attribute name="ref" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="cache-ref">
+        <xs:attribute name="cache-ref" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="user-service-ref">
+        <xs:attribute name="user-service-ref" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="password-encoder">
         <xs:annotation>
-
-          <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
-            context.</xs:documentation>
-
+            <xs:documentation>element which defines a password encoding strategy. Used by an
+                authentication provider to convert submitted passwords to hashed versions, for
+                example.</xs:documentation>
         </xs:annotation>
-
-      </xs:attribute>
-
-      <xs:attributeGroup ref="security:properties-file"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="properties-file">
-
-    <xs:attribute name="properties" type="xs:string"/>
-
-  </xs:attributeGroup>
-
-  <xs:element name="user">
-    <xs:annotation>
-
-      <xs:documentation>Represents a user in the application.</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attributeGroup ref="security:user.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="user.attlist">
-
-    <xs:attribute name="name" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The username assigned to the user.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="password" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The password assigned to the user. This may be hashed if the corresponding
-          authentication provider supports hashing (remember to set the "hash" attribute of the
-          "user-service" element).</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="authorities" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>One of more authorities granted to the user. Separate authorities with a
-          comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-    <xs:attribute name="locked">
-
-      <xs:annotation>
-
-        <xs:documentation>Can be set to "true" to mark an account as locked and unusable.</xs:documentation>
-
-      </xs:annotation>
-
-      <xs:simpleType>
-
-        <xs:restriction base="xs:token">
-
-          <xs:enumeration value="true"/>
-
-          <xs:enumeration value="false"/>
-
-        </xs:restriction>
-
-      </xs:simpleType>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="jdbc-user-service" substitutionGroup="security:any-user-service">
-    <xs:annotation>
-
-      <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attribute name="id" type="xs:ID">
-
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" name="salt-source">
+                    <xs:complexType>
+                        <xs:attribute name="user-property" type="xs:string">
+                            <xs:annotation>
+                                <xs:documentation>A property of the UserDetails object which will be
+                                    used as salt by a password encoder. Typically something like
+                                    "username" might be used. </xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                        <xs:attribute name="system-wide" type="xs:string">
+                            <xs:annotation>
+                                <xs:documentation>A single value that will be used as the salt for a
+                                    password encoder. </xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:password-encoder.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="password-encoder.attlist">
+        <xs:attribute name="ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Defines a reference to a Spring bean Id.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="hash">
+            <xs:annotation>
+                <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
+                    strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="plaintext"/>
+                    <xs:enumeration value="sha"/>
+                    <xs:enumeration value="md5"/>
+                    <xs:enumeration value="md4"/>
+                    <xs:enumeration value="{sha}"/>
+                    <xs:enumeration value="{ssha}"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="base64">
+            <xs:annotation>
+                <xs:documentation>Whether a string should be base64 encoded</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="user-property">
+        <xs:attribute name="user-property" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A property of the UserDetails object which will be used as salt by
+                    a password encoder. Typically something like "username" might be used. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="system-wide">
+        <xs:attribute name="system-wide" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A single value that will be used as the salt for a password
+                    encoder. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="ldap-server">
         <xs:annotation>
-
-          <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
-            context.</xs:documentation>
-
+            <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
+                indicates the location of a remote server. If no url is given, an embedded server
+                will be started, listening on the supplied port number. The port is optional and
+                defaults to 33389. A Spring LDAP ContextSource bean will be registered for the
+                server with the id supplied. </xs:documentation>
         </xs:annotation>
-
-      </xs:attribute>
-
-      <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="jdbc-user-service.attlist">
-
-    <xs:attribute name="data-source-ref" use="required" type="xs:string">
-
-      <xs:annotation>
-
-        <xs:documentation>The bean ID of the DataSource which provides the required tables.</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:element name="any-user-service" abstract="true"/>
-
-  <xs:group name="custom-filter">
-
-    <xs:sequence>
-
-      <xs:element minOccurs="0" ref="security:custom-filter"/>
-
-    </xs:sequence>
-
-  </xs:group>
-
-  <xs:element name="custom-filter">
-    <xs:annotation>
-
-      <xs:documentation>Used to indicate that a filter bean declaration should be incorporated into
-        the security filter chain. If neither the 'after' or 'before' options are supplied, then the
-        filter must implement the Ordered interface directly. </xs:documentation>
-
-    </xs:annotation>
-    <xs:complexType>
-
-      <xs:attribute name="after" type="security:named-security-filter">
-
+        <xs:complexType>
+            <xs:attributeGroup ref="security:ldap-server.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="ldap-server.attlist">
+        <xs:attribute name="id" type="xs:ID">
+            <xs:annotation>
+                <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
+                    context.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="url" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Specifies a URL.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="port" type="xs:integer">
+            <xs:annotation>
+                <xs:documentation>Specifies an IP port number. Used to configure an embedded LDAP
+                    server, for example.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="manager-dn" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Username (DN) of the "manager" user identity which will be used to
+                    authenticate to a (non-embedded) LDAP server. If omitted, anonymous access will
+                    be used. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="manager-password" type="xs:string"/>
+        <xs:attribute name="ldif" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Explicitly specifies an ldif file resource to load into an
+                    embedded LDAP server</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="root" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Optional root suffix for the embedded LDAP server. Default is
+                    "dc=springframework,dc=org"</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="ldap-server-ref-attribute">
+        <xs:attribute name="server-ref" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The optional server to use. If omitted, and a default LDAP server
+                    is registered (using &lt;ldap-server&gt; with no Id), that server will
+                    be used. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="group-search-filter-attribute">
+        <xs:attribute name="group-search-filter" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The
+                    substituted parameter is the DN of the user.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="group-search-base-attribute">
+        <xs:attribute name="group-search-base" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Search base for group membership searches. Defaults to
+                    "ou=groups".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="user-search-filter-attribute">
+        <xs:attribute name="user-search-filter" use="required" type="xs:string"/>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="user-search-base-attribute">
+        <xs:attribute name="user-search-base" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="group-role-attribute-attribute">
+        <xs:attribute name="group-role-attribute" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The LDAP attribute name which contains the role name which will be
+                    used within Spring Security. Defaults to "cn".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="ldap-user-service">
+        <xs:complexType>
+            <xs:attributeGroup ref="security:ldap-us.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="ldap-us.attlist">
+        <xs:attribute name="id" type="xs:ID">
+            <xs:annotation>
+                <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
+                    context.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="server-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The optional server to use. If omitted, and a default LDAP server
+                    is registered (using &lt;ldap-server&gt; with no Id), that server will
+                    be used. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="user-search-filter" type="xs:string"/>
+        <xs:attributeGroup ref="security:user-search-base-attribute"/>
+        <xs:attribute name="group-search-filter" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The
+                    substituted parameter is the DN of the user.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="group-search-base" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Search base for group membership searches. Defaults to
+                    "ou=groups".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="group-role-attribute" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The LDAP attribute name which contains the role name which will be
+                    used within Spring Security. Defaults to "cn".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="cache-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="ldap-authentication-provider">
         <xs:annotation>
-
-          <xs:documentation>The filter immediately after which the custom-filter should be placed in
-            the chain. This feature will only be needed by advanced users who wish to mix their own
-            filters into the security filter chain and have some knowledge of the standard Spring
-            Security filters. The filter names map to specific Spring Security implementation
-            filters. </xs:documentation>
-
+            <xs:documentation>Sets up an ldap authentication provider</xs:documentation>
         </xs:annotation>
-
-      </xs:attribute>
-
-      <xs:attribute name="before" type="security:named-security-filter">
-
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" ref="security:password-compare"/>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:ldap-ap.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="ldap-ap.attlist">
+        <xs:attribute name="server-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The optional server to use. If omitted, and a default LDAP server
+                    is registered (using &lt;ldap-server&gt; with no Id), that server will
+                    be used. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attributeGroup ref="security:user-search-base-attribute"/>
+        <xs:attribute name="user-search-filter" type="xs:string"/>
+        <xs:attribute name="group-search-base" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Search base for group membership searches. Defaults to
+                    "ou=groups".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="group-search-filter" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The
+                    substituted parameter is the DN of the user.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="group-role-attribute" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The LDAP attribute name which contains the role name which will be
+                    used within Spring Security. Defaults to "cn".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="user-dn-pattern" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A specific pattern used to build the user's DN, for example
+                    "uid={0},ou=people". The key "{0}" must be present and will be substituted with
+                    the username.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="password-compare">
         <xs:annotation>
-
-          <xs:documentation>The filter immediately before which the custom-filter should be placed
-            in the chain</xs:documentation>
-
+            <xs:documentation>Specifies that an LDAP provider should use an LDAP compare operation
+                of the user's password to authenticate the user</xs:documentation>
         </xs:annotation>
-
-      </xs:attribute>
-
-    </xs:complexType>
-  </xs:element>
-
-  <xs:attributeGroup name="after">
-
-    <xs:attribute name="after" use="required" type="security:named-security-filter">
-
-      <xs:annotation>
-
-        <xs:documentation>The filter immediately after which the custom-filter should be placed in
-          the chain. This feature will only be needed by advanced users who wish to mix their own
-          filters into the security filter chain and have some knowledge of the standard Spring
-          Security filters. The filter names map to specific Spring Security implementation filters. </xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:attributeGroup name="before">
-
-    <xs:attribute name="before" use="required" type="security:named-security-filter">
-
-      <xs:annotation>
-
-        <xs:documentation>The filter immediately before which the custom-filter should be placed in
-          the chain</xs:documentation>
-
-      </xs:annotation>
-
-    </xs:attribute>
-
-  </xs:attributeGroup>
-
-  <xs:simpleType name="named-security-filter">
-
-    <xs:restriction base="xs:token">
-
-      <xs:enumeration value="FIRST"/>
-
-      <xs:enumeration value="CHANNEL_FILTER"/>
-
-      <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
-
-      <xs:enumeration value="SESSION_CONTEXT_INTEGRATION_FILTER"/>
-
-      <xs:enumeration value="LOGOUT_FILTER"/>
-
-      <xs:enumeration value="X509_FILTER"/>
-
-      <xs:enumeration value="PRE_AUTH_FILTER"/>
-
-      <xs:enumeration value="CAS_PROCESSING_FILTER"/>
-
-      <xs:enumeration value="AUTHENTICATION_PROCESSING_FILTER"/>
-
-      <xs:enumeration value="BASIC_PROCESSING_FILTER"/>
-
-      <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
-
-      <xs:enumeration value="REMEMBER_ME_FILTER"/>
-
-      <xs:enumeration value="ANONYMOUS_FILTER"/>
-
-      <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
-
-      <xs:enumeration value="NTLM_FILTER"/>
-
-      <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
-
-      <xs:enumeration value="SWITCH_USER_FILTER"/>
-
-    </xs:restriction>
-
-  </xs:simpleType>
-
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" ref="security:password-encoder"/>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:password-compare.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="password-compare.attlist">
+        <xs:attribute name="password-attribute" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The attribute in the directory which contains the user password.
+                    Defaults to "userPassword".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="hash">
+            <xs:annotation>
+                <xs:documentation>Defines the hashing algorithm used on user passwords. We recommend
+                    strongly against using MD4, as it is a very weak hashing algorithm.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="plaintext"/>
+                    <xs:enumeration value="sha"/>
+                    <xs:enumeration value="md5"/>
+                    <xs:enumeration value="md4"/>
+                    <xs:enumeration value="{sha}"/>
+                    <xs:enumeration value="{ssha}"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="intercept-methods">
+        <xs:annotation>
+            <xs:documentation>Can be used inside a bean definition to add a security interceptor to
+                the bean and set up access configuration attributes for the bean's methods</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="unbounded" ref="security:protect"/>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:intercept-methods.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="intercept-methods.attlist">
+        <xs:attribute name="access-decision-manager-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Optional AccessDecisionManager bean ID to be used by the created
+                    method security interceptor.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="protect">
+        <xs:annotation>
+            <xs:documentation>Defines a protected method and the access control configuration
+                attributes that apply to it. We strongly advise you NOT to mix "protect"
+                declarations with any services provided "global-method-security".</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attributeGroup ref="security:protect.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="protect.attlist">
+        <xs:attribute name="method" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A method name</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="access" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Access configuration attributes list that applies to the method,
+                    e.g. "ROLE_A,ROLE_B".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="global-method-security">
+        <xs:annotation>
+            <xs:documentation>Provides method security for all beans registered in the Spring
+                application context. Specifically, beans will be scanned for Spring Security
+                annotations and/or matches with the ordered list of "protect-pointcut" sub-elements.
+                Where there is a match, the beans will automatically be proxied and security
+                authorization applied to the methods accordingly. If you use and enable all three
+                sources of method security metadata (ie "protect-pointcut" declarations, @Secured
+                and also JSR 250 security annotations), the metadata sources will be queried in that
+                order. In practical terms, this enables you to use XML to override method security
+                metadata expressed by way of @Secured annotations, with @Secured annotations
+                overriding method security metadata expressed by JSR 250 annotations. It is
+                perfectly acceptable to mix and match, with a given Java type using a combination of
+                XML, @Secured and JSR 250 to express method security metadata (albeit on different
+                methods).</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="unbounded" name="protect-pointcut">
+                    <xs:annotation>
+                        <xs:documentation>Defines a protected pointcut and the access control
+                            configuration attributes that apply to it. Every bean registered in the
+                            Spring application context that provides a method that matches the
+                            pointcut will receive security authorization.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:protect-pointcut.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:global-method-security.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="global-method-security.attlist">
+        <xs:attribute name="secured-annotations">
+            <xs:annotation>
+                <xs:documentation>Specifies whether the use of Spring Security's @Secured
+                    annotations should be enabled for this application context. Please ensure you
+                    have the spring-security-tiger-xxx.jar on the classpath. Defaults to "disabled".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="disabled"/>
+                    <xs:enumeration value="enabled"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="jsr250-annotations">
+            <xs:annotation>
+                <xs:documentation>Specifies whether JSR-250 style attributes are to be used (for
+                    example "RolesAllowed"). This will require the javax.annotation.security classes
+                    on the classpath. Defaults to "disabled".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="disabled"/>
+                    <xs:enumeration value="enabled"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="access-decision-manager-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Optional AccessDecisionManager bean ID to override the default
+                    used for method security.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="protect-pointcut.attlist">
+        <xs:attribute name="expression" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>An AspectJ expression, including the 'execution' keyword. For
+                    example, 'execution(int com.foo.TargetObject.countLength(String))' (without the
+                    quotes).</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="access" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Access configuration attributes list that applies to all methods
+                    matching the pointcut, e.g. "ROLE_A,ROLE_B"</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="http">
+        <xs:annotation>
+            <xs:documentation>Container element for HTTP security configuration</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:element name="intercept-url">
+                    <xs:annotation>
+                        <xs:documentation>Specifies the access attributes and/or filter list for a
+                            particular set of URLs.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:intercept-url.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="form-login">
+                    <xs:annotation>
+                        <xs:documentation>Sets up a form login configuration for authentication with
+                            a username and password</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:form-login.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element ref="security:openid-login"/>
+                <xs:element name="x509">
+                    <xs:annotation>
+                        <xs:documentation>Adds support for X.509 client authentication.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:x509.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="http-basic">
+                    <xs:annotation>
+                        <xs:documentation>Adds support for basic authentication (this is an element
+                            to permit future expansion, such as supporting an "ignoreFailure"
+                            attribute)</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType/>
+                </xs:element>
+                <xs:element name="logout">
+                    <xs:annotation>
+                        <xs:documentation>Incorporates a logout processing filter. Most web
+                            applications require a logout filter, although you may not require one
+                            if you write a controller to provider similar logic.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:logout.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="concurrent-session-control">
+                    <xs:annotation>
+                        <xs:documentation>Adds support for concurrent session control, allowing
+                            limits to be placed on the number of sessions a user can have.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:concurrent-sessions.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="remember-me">
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:remember-me.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="anonymous">
+                    <xs:annotation>
+                        <xs:documentation>Adds support for automatically granting all anonymous web
+                            requests a particular principal identity and a corresponding granted
+                            authority.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:anonymous.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="port-mappings">
+                    <xs:annotation>
+                        <xs:documentation>Defines the list of mappings between http and https ports
+                            for use in redirects</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element maxOccurs="unbounded" ref="security:port-mapping"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:choice>
+            <xs:attributeGroup ref="security:http.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="http.attlist">
+        <xs:attribute name="auto-config">
+            <xs:annotation>
+                <xs:documentation>Automatically registers a login form, BASIC authentication,
+                    anonymous authentication, logout services, remember-me and
+                    servlet-api-integration. If set to "true", all of these capabilities are added
+                    (although you can still customize the configuration of each by providing the
+                    respective element). If unspecified, defaults to "false".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="create-session">
+            <xs:annotation>
+                <xs:documentation>Controls the eagerness with which an HTTP session is created. If
+                    not set, defaults to "ifRequired".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="ifRequired"/>
+                    <xs:enumeration value="always"/>
+                    <xs:enumeration value="never"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="path-type">
+            <xs:annotation>
+                <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
+                    1.4-compatible regular expressions, or Apache Ant expressions). Defaults to
+                    "ant" if unspecified.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="ant"/>
+                    <xs:enumeration value="regex"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="lowercase-comparisons">
+            <xs:annotation>
+                <xs:documentation>Whether test URLs should be converted to lower case prior to
+                    comparing with defined path patterns. If unspecified, defaults to "true".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="servlet-api-provision">
+            <xs:annotation>
+                <xs:documentation>Provides versions of HttpServletRequest security methods such as
+                    isUserInRole() and getPrincipal() which are implemented by accessing the Spring
+                    SecurityContext. Defaults to "true".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="access-decision-manager-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Optional attribute specifying the ID of the AccessDecisionManager
+                    implementation which should be used for authorizing HTTP requests.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="realm" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Optional attribute specifying the realm name that will be used for
+                    all authentication features that require a realm name (eg BASIC and Digest
+                    authentication). If unspecified, defaults to "Spring Security Application".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="session-fixation-protection">
+            <xs:annotation>
+                <xs:documentation>Indicates whether an existing session should be invalidated when a
+                    user authenticates and a new session started. If set to "none" no change will be
+                    made. "newSession" will create a new empty session. "migrateSession" will create
+                    a new session and copy the session attributes to the new session. Defaults to
+                    "migrateSession".</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="none"/>
+                    <xs:enumeration value="newSession"/>
+                    <xs:enumeration value="migrateSession"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="intercept-url.attlist">
+        <xs:attribute name="pattern" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The pattern which defines the URL path. The content will depend on
+                    the type set in the containing http element, so will default to ant path syntax.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="access" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The access configuration attributes that apply for the configured
+                    path.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="method">
+            <xs:annotation>
+                <xs:documentation>The HTTP Method for which the access configuration attributes
+                    should apply. If not specified, the attributes will apply to any method.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="GET"/>
+                    <xs:enumeration value="DELETE"/>
+                    <xs:enumeration value="HEAD"/>
+                    <xs:enumeration value="OPTIONS"/>
+                    <xs:enumeration value="POST"/>
+                    <xs:enumeration value="PUT"/>
+                    <xs:enumeration value="TRACE"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="filters">
+            <xs:annotation>
+                <xs:documentation>The filter list for the path. Currently can be set to "none" to
+                    remove a path from having any filters applied. The full filter stack (consisting
+                    of all defined filters, will be applied to any other paths).</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="none"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="requires-channel">
+            <xs:annotation>
+                <xs:documentation>Used to specify that a URL must be accessed over http or https</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="http"/>
+                    <xs:enumeration value="https"/>
+                    <xs:enumeration value="any"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="logout.attlist">
+        <xs:attribute name="logout-url" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Specifies the URL that will cause a logout. Spring Security will
+                    initialize a filter that responds to this particular URL. Defaults to
+                    /j_spring_security_logout if unspecified.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="logout-success-url" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Specifies the URL to display once the user has logged out. If not
+                    specified, defaults to /.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="invalidate-session">
+            <xs:annotation>
+                <xs:documentation>Specifies whether a logout also causes HttpSession invalidation,
+                    which is generally desirable. If unspecified, defaults to true.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="form-login.attlist">
+        <xs:attribute name="login-processing-url" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The URL that the login form is posted to. If unspecified, it
+                    defaults to /j_spring_security_check.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="default-target-url" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The URL that will be redirected to after successful
+                    authentication, if the user's previous action could not be resumed. This
+                    generally happens if the user visits a login page without having first requested
+                    a secured operation that triggers authentication. If unspecified, defaults to
+                    the root of the application.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="login-page" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The URL for the login page. If no login URL is specified, Spring
+                    Security will automatically create a login URL at /spring_security_login and a
+                    corresponding filter to render that login URL when requested.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="authentication-failure-url" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The URL for the login failure page. If no login failure URL is
+                    specified, Spring Security will automatically create a failure login URL at
+                    /spring_security_login?login_error and a corresponding filter to render that
+                    login failure URL when requested.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="openid-login">
+        <xs:annotation>
+            <xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attributeGroup ref="security:form-login.attlist"/>
+            <xs:attribute name="user-service-ref" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="filter-chain-map">
+        <xs:annotation>
+            <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a
+                FilterChainMap</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="unbounded" name="filter-chain">
+                    <xs:annotation>
+                        <xs:documentation>Used within filter-chain-map to define a specific URL
+                            pattern and the list of filters which apply to the URLs matching that
+                            pattern. When multiple filter-chain elements are used within a
+                            filter-chain-map element, the most specific patterns must be placed at
+                            the top of the list, with most general ones at the bottom.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:filter-chain.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:filter-chain-map.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="filter-chain-map.attlist">
+        <xs:attributeGroup ref="security:path-type"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="filter-chain.attlist">
+        <xs:attribute name="pattern" use="required" type="xs:string"/>
+        <xs:attribute name="filters" use="required" type="xs:string"/>
+    </xs:attributeGroup>
+    <xs:element name="filter-invocation-definition-source">
+        <xs:annotation>
+            <xs:documentation>Used to explicitly configure a FilterInvocationDefinitionSource bean
+                for use with a FilterSecurityInterceptor. Usually only needed if you are configuring
+                a FilterChainProxy explicitly, rather than using the &lt;http&gt; element.
+                The intercept-url elements used should only contain pattern, method and access
+                attributes. Any others will result in a configuration error. </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="unbounded" name="intercept-url">
+                    <xs:annotation>
+                        <xs:documentation>Specifies the access attributes and/or filter list for a
+                            particular set of URLs.</xs:documentation>
+                    </xs:annotation>
+                    <xs:complexType>
+                        <xs:attributeGroup ref="security:intercept-url.attlist"/>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+            <xs:attributeGroup ref="security:fids.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="fids.attlist">
+        <xs:attribute name="id" type="xs:ID">
+            <xs:annotation>
+                <xs:documentation>A bean identifier, used for referring to the bean elsewhere in the
+                    context.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="lowercase-comparisons">
+            <xs:annotation>
+                <xs:documentation>as for http element</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="path-type">
+            <xs:annotation>
+                <xs:documentation>Defines the type of pattern used to specify URL paths (either JDK
+                    1.4-compatible regular expressions, or Apache Ant expressions). Defaults to
+                    "ant" if unspecified.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="ant"/>
+                    <xs:enumeration value="regex"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="concurrent-sessions.attlist">
+        <xs:attribute name="max-sessions" type="xs:positiveInteger"/>
+        <xs:attribute name="expired-url" type="xs:string"/>
+        <xs:attribute name="exception-if-maximum-exceeded">
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="remember-me.attlist">
+        <xs:attribute name="key" type="xs:string"/>
+        <xs:attribute name="token-repository-ref" type="xs:string"/>
+        <xs:attribute name="data-source-ref" type="xs:string"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="anonymous.attlist">
+        <xs:attribute name="key" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The key shared between the provider and filter. This generally
+                    does not need to be set. If unset, it will default to "doesNotMatter".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="username" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The username that should be assigned to the anonymous request.
+                    This allows the principal to be identified, which may be important for logging
+                    and auditing. if unset, defaults to "anonymousUser".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="granted-authority" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The granted authority that should be assigned to the anonymous
+                    request. Commonly this is used to assign the anonymous request particular roles,
+                    which can subsequently be used in authorization decisions. If unset, defaults to
+                    "ROLE_ANONYMOUS".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+
+    <xs:element name="port-mapping">
+        <xs:complexType>
+            <xs:attributeGroup ref="security:http-port"/>
+            <xs:attributeGroup ref="security:https-port"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="http-port">
+        <xs:attribute name="http" use="required" type="xs:integer"/>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="https-port">
+        <xs:attribute name="https" use="required" type="xs:integer"/>
+    </xs:attributeGroup>
+
+    <xs:attributeGroup name="x509.attlist">
+        <xs:attribute name="subject-principal-regex" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The regular expression used to obtain the username from the
+                    certificate's subject. Defaults to matching on the common name using the pattern
+                    "CN=(.*?),".</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="user-service-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="authentication-manager">
+        <xs:annotation>
+            <xs:documentation>If you are using namespace configuration with Spring Security, an
+                AuthenticationManager will automatically be registered. This element simple allows
+                you to define an alias to allow you to reference the authentication-manager in your
+                own beans. </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attributeGroup ref="security:authman.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="authman.attlist">
+        <xs:annotation>
+            <xs:documentation>The alias you wish to use for the AuthenticationManager bean</xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="alias" use="required" type="xs:ID"/>
+    </xs:attributeGroup>
+    <xs:element name="authentication-provider">
+        <xs:annotation>
+            <xs:documentation>Indicates that the contained user-service should be used as an
+                authentication source. </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:choice minOccurs="0" maxOccurs="unbounded">
+                <xs:group ref="security:any-user-service"/>
+                <xs:element ref="security:password-encoder"/>
+            </xs:choice>
+            <xs:attributeGroup ref="security:ap.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="ap.attlist">
+        <xs:attribute name="user-service-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>A reference to a user-service (or UserDetailsService bean) Id</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="custom-authentication-provider">
+        <xs:complexType/>
+    </xs:element>
+    <xs:element name="user-service">
+        <xs:annotation>
+            <xs:documentation>Creates an in-memory UserDetailsService from a properties file or a
+                list of "user" child elements.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:user"/>
+            </xs:sequence>
+            <xs:attribute name="id" type="xs:ID">
+                <xs:annotation>
+                    <xs:documentation>A bean identifier, used for referring to the bean elsewhere in
+                        the context.</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attributeGroup ref="security:properties-file"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="properties-file">
+        <xs:attribute name="properties" type="xs:string"/>
+    </xs:attributeGroup>
+    <xs:element name="user">
+        <xs:annotation>
+            <xs:documentation>Represents a user in the application.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attributeGroup ref="security:user.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="user.attlist">
+        <xs:attribute name="name" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The username assigned to the user.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="password" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The password assigned to the user. This may be hashed if the
+                    corresponding authentication provider supports hashing (remember to set the
+                    "hash" attribute of the "user-service" element).</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="authorities" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>One of more authorities granted to the user. Separate authorities
+                    with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR"</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="locked">
+            <xs:annotation>
+                <xs:documentation>Can be set to "true" to mark an account as locked and unusable.</xs:documentation>
+            </xs:annotation>
+            <xs:simpleType>
+                <xs:restriction base="xs:token">
+                    <xs:enumeration value="true"/>
+                    <xs:enumeration value="false"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:element name="jdbc-user-service">
+        <xs:annotation>
+            <xs:documentation>Causes creation of a JDBC-based UserDetailsService.</xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attribute name="id" type="xs:ID">
+                <xs:annotation>
+                    <xs:documentation>A bean identifier, used for referring to the bean elsewhere in
+                        the context.</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attributeGroup ref="security:jdbc-user-service.attlist"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="jdbc-user-service.attlist">
+        <xs:attribute name="data-source-ref" use="required" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>The bean ID of the DataSource which provides the required tables.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="cache-ref" type="xs:string">
+            <xs:annotation>
+                <xs:documentation>Defines a reference to a cache for use with a UserDetailsService.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:group name="any-user-service">
+        <xs:choice>
+            <xs:element ref="security:user-service"/>
+            <xs:element ref="security:jdbc-user-service"/>
+            <xs:element ref="security:ldap-user-service"/>
+        </xs:choice>
+    </xs:group>
+    <xs:group name="custom-filter">
+        <xs:sequence>
+            <xs:element minOccurs="0" ref="security:custom-filter"/>
+        </xs:sequence>
+    </xs:group>
+    <xs:element name="custom-filter">
+        <xs:annotation>
+            <xs:documentation>Used to indicate that a filter bean declaration should be incorporated
+                into the security filter chain. If neither the 'after' or 'before' options are
+                supplied, then the filter must implement the Ordered interface directly. </xs:documentation>
+        </xs:annotation>
+        <xs:complexType>
+            <xs:attribute name="after" type="security:named-security-filter">
+                <xs:annotation>
+                    <xs:documentation>The filter immediately after which the custom-filter should be
+                        placed in the chain. This feature will only be needed by advanced users who
+                        wish to mix their own filters into the security filter chain and have some
+                        knowledge of the standard Spring Security filters. The filter names map to
+                        specific Spring Security implementation filters. </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="before" type="security:named-security-filter">
+                <xs:annotation>
+                    <xs:documentation>The filter immediately before which the custom-filter should
+                        be placed in the chain</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+        </xs:complexType>
+    </xs:element>
+    <xs:attributeGroup name="after">
+        <xs:attribute name="after" use="required" type="security:named-security-filter">
+            <xs:annotation>
+                <xs:documentation>The filter immediately after which the custom-filter should be
+                    placed in the chain. This feature will only be needed by advanced users who wish
+                    to mix their own filters into the security filter chain and have some knowledge
+                    of the standard Spring Security filters. The filter names map to specific Spring
+                    Security implementation filters. </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:attributeGroup name="before">
+        <xs:attribute name="before" use="required" type="security:named-security-filter">
+            <xs:annotation>
+                <xs:documentation>The filter immediately before which the custom-filter should be
+                    placed in the chain</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:attributeGroup>
+    <xs:simpleType name="named-security-filter">
+        <xs:restriction base="xs:token">
+            <xs:enumeration value="FIRST"/>
+            <xs:enumeration value="CHANNEL_FILTER"/>
+            <xs:enumeration value="CONCURRENT_SESSION_FILTER"/>
+            <xs:enumeration value="SESSION_CONTEXT_INTEGRATION_FILTER"/>
+            <xs:enumeration value="LOGOUT_FILTER"/>
+            <xs:enumeration value="X509_FILTER"/>
+            <xs:enumeration value="PRE_AUTH_FILTER"/>
+            <xs:enumeration value="CAS_PROCESSING_FILTER"/>
+            <xs:enumeration value="AUTHENTICATION_PROCESSING_FILTER"/>
+            <xs:enumeration value="BASIC_PROCESSING_FILTER"/>
+            <xs:enumeration value="SERVLET_API_SUPPORT_FILTER"/>
+            <xs:enumeration value="REMEMBER_ME_FILTER"/>
+            <xs:enumeration value="ANONYMOUS_FILTER"/>
+            <xs:enumeration value="EXCEPTION_TRANSLATION_FILTER"/>
+            <xs:enumeration value="NTLM_FILTER"/>
+            <xs:enumeration value="FILTER_SECURITY_INTERCEPTOR"/>
+            <xs:enumeration value="SWITCH_USER_FILTER"/>
+        </xs:restriction>
+    </xs:simpleType>
 </xs:schema>

+ 35 - 9
core/src/test/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParserTests.java

@@ -1,16 +1,17 @@
 package org.springframework.security.config;
 
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
-import org.junit.Test;
 import org.junit.After;
-
-import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
-import org.springframework.security.util.InMemoryXmlApplicationContext;
+import org.junit.Test;
 import org.springframework.security.AuthenticationManager;
+import org.springframework.security.providers.ProviderManager;
 import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
-
-import javax.sql.DataSource;
+import org.springframework.security.providers.dao.DaoAuthenticationProvider;
+import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager;
+import org.springframework.security.util.InMemoryXmlApplicationContext;
 
 /**
  * @author Ben Alex
@@ -18,7 +19,7 @@ import javax.sql.DataSource;
  * @version $Id$
  */
 public class JdbcUserServiceBeanDefinitionParserTests {
-    private InMemoryXmlApplicationContext appContext;
+    private static String USER_CACHE_XML = "<b:bean id='userCache' class='org.springframework.security.providers.dao.MockUserCache'/>";	
 
     private static String DATA_SOURCE =
             "    <b:bean id='populator' class='org.springframework.security.config.DataSourcePopulator'>" +
@@ -29,6 +30,8 @@ public class JdbcUserServiceBeanDefinitionParserTests {
             "        <b:constructor-arg value='jdbcnamespaces'/>" +
             "    </b:bean>";
 
+    private InMemoryXmlApplicationContext appContext;
+    
     @After
     public void closeAppContext() {
         if (appContext != null) {
@@ -45,10 +48,20 @@ public class JdbcUserServiceBeanDefinitionParserTests {
 
     @Test
     public void beanIdIsParsedCorrectly() {
-        setContext("<jdbc-user-service id='customUserService' data-source-ref='dataSource'/>" + DATA_SOURCE);
-        JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("customUserService");
+        setContext("<jdbc-user-service id='myUserService' data-source-ref='dataSource'/>" + DATA_SOURCE);
+        JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
     }
 
+    @Test
+    public void cacheRefIsparsedCorrectly() {
+        setContext("<jdbc-user-service id='myUserService' cache-ref='userCache' data-source-ref='dataSource'/>" 
+        		+ DATA_SOURCE +USER_CACHE_XML);
+        JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService");
+        CachingUserDetailsService cachingUserService = 
+        	(CachingUserDetailsService) appContext.getBean("myUserService" + AbstractUserDetailsServiceBeanDefinitionParser.CACHING_SUFFIX);
+        assertSame(cachingUserService.getUserCache(), appContext.getBean("userCache"));
+    }    
+    
     @Test
     public void isSupportedByAuthenticationProviderElement() {
         setContext(
@@ -59,6 +72,19 @@ public class JdbcUserServiceBeanDefinitionParserTests {
         mgr.authenticate(new UsernamePasswordAuthenticationToken("rod", "koala"));
     }
 
+    @Test
+    public void cacheIsInjectedIntoAuthenticationProvider() {
+        setContext(
+                "<authentication-provider>" +
+                "    <jdbc-user-service cache-ref='userCache' data-source-ref='dataSource'/>" +
+                "</authentication-provider>" + DATA_SOURCE + USER_CACHE_XML);
+        ProviderManager mgr = (ProviderManager) appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
+        DaoAuthenticationProvider provider = (DaoAuthenticationProvider) mgr.getProviders().get(0);
+        assertSame(provider.getUserCache(), appContext.getBean("userCache"));
+        provider.authenticate(new UsernamePasswordAuthenticationToken("rod","koala"));
+        assertNotNull("Cache should contain user after authentication", provider.getUserCache().getUserFromCache("rod"));      
+    }
+
     private void setContext(String context) {
         appContext = new InMemoryXmlApplicationContext(context);
     }