diff --git a/config/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java index ead989303b..017961399e 100644 --- a/config/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java @@ -97,7 +97,7 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { ldapProvider.addConstructorArgValue(authenticatorBuilder.getBeanDefinition()); ldapProvider.addConstructorArgValue(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext)); ldapProvider.addPropertyValue("userDetailsContextMapper", - LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext)); + LdapUserServiceBeanDefinitionParser.parseUserDetailsClassOrUserMapperRef(elt, parserContext)); parserContext.getRegistry().registerBeanDefinition(BeanIds.LDAP_AUTHENTICATION_PROVIDER, ldapProvider.getBeanDefinition()); ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.LDAP_AUTHENTICATION_PROVIDER); diff --git a/config/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java index bca4e3d218..54920a4c77 100644 --- a/config/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java @@ -1,5 +1,6 @@ package org.springframework.security.config; +import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; @@ -29,6 +30,7 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ static final String ATT_ROLE_PREFIX = "role-prefix"; static final String ATT_USER_CLASS = "user-details-class"; + static final String ATT_USER_CONTEXT_MAPPER_REF = "user-context-mapper-ref"; static final String OPT_PERSON = "person"; static final String OPT_INETORGPERSON = "inetOrgPerson"; @@ -49,8 +51,9 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ } builder.addConstructorArgValue(parseSearchBean(elt, parserContext)); + builder.getRawBeanDefinition().setSource(parserContext.extractSource(elt)); builder.addConstructorArgValue(parseAuthoritiesPopulator(elt, parserContext)); - builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext)); + builder.addPropertyValue("userDetailsMapper", parseUserDetailsClassOrUserMapperRef(elt, parserContext)); } static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) { @@ -109,15 +112,32 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ registry.registerBeanDefinition(BeanIds.CONTEXT_SOURCE_SETTING_POST_PROCESSOR, bdb.getBeanDefinition()); } - static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) { + static BeanMetadataElement parseUserDetailsClassOrUserMapperRef(Element elt, ParserContext parserContext) { String userDetailsClass = elt.getAttribute(ATT_USER_CLASS); + String userMapperRef = elt.getAttribute(ATT_USER_CONTEXT_MAPPER_REF); + + if (StringUtils.hasText(userDetailsClass) && StringUtils.hasText(userMapperRef)) { + parserContext.getReaderContext().error("Attributes " + ATT_USER_CLASS + " and " + ATT_USER_CONTEXT_MAPPER_REF + + " cannot be used together.", parserContext.extractSource(elt)); + } + + if (StringUtils.hasText(userMapperRef)) { + return new RuntimeBeanReference(userMapperRef); + } + + RootBeanDefinition mapper; if (OPT_PERSON.equals(userDetailsClass)) { - return new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null); + mapper = new RootBeanDefinition(PERSON_MAPPER_CLASS, null, null); } else if (OPT_INETORGPERSON.equals(userDetailsClass)) { - return new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null); + mapper = new RootBeanDefinition(INET_ORG_PERSON_MAPPER_CLASS, null, null); + } else { + mapper = new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null); } - return new RootBeanDefinition(LDAP_USER_MAPPER_CLASS, null, null); + + mapper.setSource(parserContext.extractSource(elt)); + + return mapper; } static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) { diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc index eb44da6f56..a1539d882d 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc @@ -106,6 +106,9 @@ group-role-attribute-attribute = user-details-class-attribute = ## Allows the objectClass of the user entry to be specified. If set, the framework will attempt to load standard attributes for the defined class into the returned UserDetails object attribute user-details-class {"person" | "inetOrgPerson"} +user-context-mapper-attribute = + ## Allows explicit customization of the loaded user object by specifying a UserDetailsContextMapper bean which will be called with the context information from the user's directory entry + attribute user-context-mapper-ref {xsd:token} ldap-user-service = @@ -128,7 +131,7 @@ ldap-us.attlist &= ldap-us.attlist &= role-prefix? ldap-us.attlist &= - user-details-class-attribute? + (user-details-class-attribute | user-context-mapper-attribute)? ldap-authentication-provider = ## Sets up an ldap authentication provider @@ -151,7 +154,7 @@ ldap-ap.attlist &= ldap-ap.attlist &= role-prefix? ldap-ap.attlist &= - user-details-class-attribute? + (user-details-class-attribute | user-context-mapper-attribute)? password-compare-element = ## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd index 898eb24d80..79fa758e9e 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd @@ -301,6 +301,15 @@ + + + + Allows explicit customization of the loaded user object by specifying + a UserDetailsContextMapper bean which will be called with the context information + from the user's directory entry + + + @@ -376,6 +385,13 @@ + + + Allows explicit customization of the loaded user object by specifying + a UserDetailsContextMapper bean which will be called with the context information + from the user's directory entry + + @@ -504,6 +520,13 @@ + + + Allows explicit customization of the loaded user object by specifying + a UserDetailsContextMapper bean which will be called with the context information + from the user's directory entry + + @@ -623,7 +646,16 @@ - + + + Defines the SecurityExpressionHandler instance which will be + used if expression-based access-control is enabled. A default implementation + (with no ACL support) will be used if not supplied. + + + + + @@ -693,16 +725,6 @@ - - - Defines the SecurityExpressionHandler instance which will be used if - expression-based access-control is enabled. A default implementation (with no ACL - support) will be used if not supplied. - - - - - Used to decorate an AfterInvocationProvider to specify that it should be @@ -759,7 +781,21 @@ - + + + Sets up form login for authentication with an Open ID + identity + + + + + + A reference to a user-service (or UserDetailsService bean) + Id + + + + Adds support for X.509 client authentication. @@ -823,7 +859,12 @@ - + + + + + + @@ -1108,21 +1149,6 @@ - - - Sets up form login for authentication with an Open ID - identity - - - - - - A reference to a user-service (or UserDetailsService bean) - Id - - - - Used to explicitly configure a FilterChainProxy instance with a @@ -1348,12 +1374,6 @@ - - - - - - @@ -1474,7 +1494,14 @@ - + + + Represents a user in the application. + + + + + @@ -1488,14 +1515,6 @@ - - - Represents a user in the application. - - - - - diff --git a/config/src/test/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParserTests.java index 75c5da3dfa..19e3594e24 100644 --- a/config/src/test/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParserTests.java @@ -141,6 +141,18 @@ public class LdapUserServiceBeanDefinitionParserTests { assertTrue(ben instanceof InetOrgPerson); } + @Test + public void externalContextMapperIsSupported() { + setContext( + "" + + "" + + ""); + + UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS"); + UserDetails ben = uds.loadUserByUsername("ben"); + assertTrue(ben instanceof InetOrgPerson); + } + private void setContext(String context) { appCtx = new InMemoryXmlApplicationContext(context);