OPEN - issue SEC-807: Allow mapping to a standard Ldap UserDetails through the namespace
http://jira.springframework.org/browse/SEC-807. Added support for user-details-class attribute to ldap-authentication-provider and ldap-user-service.
This commit is contained in:
parent
104716fedb
commit
e4b32b8d29
|
@ -93,7 +93,9 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser {
|
|||
RootBeanDefinition ldapProvider = new RootBeanDefinition(LdapAuthenticationProvider.class);
|
||||
ldapProvider.getConstructorArgumentValues().addGenericArgumentValue(authenticator);
|
||||
ldapProvider.getConstructorArgumentValues().addGenericArgumentValue(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext));
|
||||
|
||||
ldapProvider.getPropertyValues().addPropertyValue("userDetailsContextMapper",
|
||||
LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext));
|
||||
|
||||
ConfigUtils.getRegisteredProviders(parserContext).add(ldapProvider);
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package org.springframework.security.config;
|
||||
|
||||
import org.springframework.security.userdetails.ldap.InetOrgPersonContextMapper;
|
||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsMapper;
|
||||
import org.springframework.security.userdetails.ldap.LdapUserDetailsService;
|
||||
import org.springframework.security.userdetails.ldap.PersonContextMapper;
|
||||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
|
||||
import org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
|
@ -17,7 +20,7 @@ import org.w3c.dom.Element;
|
|||
* @since 2.0
|
||||
*/
|
||||
public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServiceBeanDefinitionParser {
|
||||
public static final String ATT_SERVER = "server-ref";
|
||||
public static final String ATT_SERVER = "server-ref";
|
||||
public static final String ATT_USER_SEARCH_FILTER = "user-search-filter";
|
||||
public static final String ATT_USER_SEARCH_BASE = "user-search-base";
|
||||
public static final String DEF_USER_SEARCH_BASE = "";
|
||||
|
@ -28,7 +31,10 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
public static final String DEF_GROUP_SEARCH_FILTER = "(uniqueMember={0})";
|
||||
public static final String DEF_GROUP_SEARCH_BASE = "ou=groups";
|
||||
|
||||
static final String ATT_ROLE_PREFIX = "role-prefix";
|
||||
static final String ATT_ROLE_PREFIX = "role-prefix";
|
||||
static final String ATT_USER_CLASS = "user-details-class";
|
||||
static final String OPT_PERSON = "person";
|
||||
static final String OPT_INETORGPERSON = "inetOrgPerson";
|
||||
|
||||
protected Class getBeanClass(Element element) {
|
||||
return LdapUserDetailsService.class;
|
||||
|
@ -42,6 +48,7 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
|
||||
builder.addConstructorArg(parseSearchBean(elt, parserContext));
|
||||
builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext));
|
||||
builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext));
|
||||
}
|
||||
|
||||
static RootBeanDefinition parseSearchBean(Element elt, ParserContext parserContext) {
|
||||
|
@ -86,6 +93,17 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ
|
|||
return contextSource;
|
||||
}
|
||||
|
||||
static RootBeanDefinition parseUserDetailsClass(Element elt, ParserContext parserContext) {
|
||||
String userDetailsClass = elt.getAttribute(ATT_USER_CLASS);
|
||||
|
||||
if(OPT_PERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(PersonContextMapper.class);
|
||||
} else if (OPT_INETORGPERSON.equals(userDetailsClass)) {
|
||||
return new RootBeanDefinition(InetOrgPersonContextMapper.class);
|
||||
}
|
||||
return new RootBeanDefinition(LdapUserDetailsMapper.class);
|
||||
}
|
||||
|
||||
static RootBeanDefinition parseAuthoritiesPopulator(Element elt, ParserContext parserContext) {
|
||||
String groupSearchFilter = elt.getAttribute(ATT_GROUP_SEARCH_FILTER);
|
||||
String groupSearchBase = elt.getAttribute(ATT_GROUP_SEARCH_BASE);
|
||||
|
|
|
@ -90,10 +90,13 @@ user-search-filter-attribute =
|
|||
attribute user-search-filter {xsd:string}
|
||||
user-search-base-attribute =
|
||||
## Search base for user searches. Defaults to "".
|
||||
attribute user-search-base {xsd:string}?
|
||||
attribute user-search-base {xsd:string}
|
||||
group-role-attribute-attribute =
|
||||
## The LDAP attribute name which contains the role name which will be used within Spring Security. Defaults to "cn".
|
||||
attribute group-role-attribute {xsd:string}
|
||||
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"}
|
||||
|
||||
|
||||
ldap-user-service =
|
||||
|
@ -115,6 +118,8 @@ ldap-us.attlist &=
|
|||
cache-ref?
|
||||
ldap-us.attlist &=
|
||||
role-prefix?
|
||||
ldap-us.attlist &=
|
||||
user-details-class-attribute?
|
||||
|
||||
ldap-authentication-provider =
|
||||
## Sets up an ldap authentication provider
|
||||
|
@ -136,6 +141,8 @@ ldap-ap.attlist &=
|
|||
attribute user-dn-pattern {xsd:string}?
|
||||
ldap-ap.attlist &=
|
||||
role-prefix?
|
||||
ldap-ap.attlist &=
|
||||
user-details-class-attribute?
|
||||
|
||||
password-compare-element =
|
||||
## Specifies that an LDAP provider should use an LDAP compare operation of the user's password to authenticate the user
|
||||
|
|
|
@ -238,7 +238,7 @@
|
|||
<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:attribute name="user-search-base" use="required" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Search base for user searches. Defaults to "".</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
@ -252,6 +252,21 @@
|
|||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:attributeGroup name="user-details-class-attribute">
|
||||
<xs:attribute name="user-details-class" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>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</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="person"/>
|
||||
<xs:enumeration value="inetOrgPerson"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="ldap-user-service" substitutionGroup="security:any-user-service">
|
||||
<xs:complexType>
|
||||
<xs:attributeGroup ref="security:ldap-us.attlist"/>
|
||||
|
@ -272,7 +287,11 @@
|
|||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="user-search-filter" type="xs:string"/>
|
||||
<xs:attributeGroup ref="security: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:attribute name="group-search-filter" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Group search filter. Defaults to (uniqueMember={0}). The substituted
|
||||
|
@ -303,6 +322,19 @@
|
|||
persistent storage (e.g. "ROLE_").</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="user-details-class">
|
||||
<xs:annotation>
|
||||
<xs:documentation>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</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="person"/>
|
||||
<xs:enumeration value="inetOrgPerson"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="ldap-authentication-provider">
|
||||
<xs:annotation>
|
||||
|
@ -362,7 +394,11 @@
|
|||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attributeGroup ref="security: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:attribute name="user-search-filter" type="xs:string"/>
|
||||
<xs:attribute name="group-search-base" type="xs:string">
|
||||
<xs:annotation>
|
||||
|
@ -395,6 +431,19 @@
|
|||
persistent storage (e.g. "ROLE_").</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="user-details-class">
|
||||
<xs:annotation>
|
||||
<xs:documentation>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</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="person"/>
|
||||
<xs:enumeration value="inetOrgPerson"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:attributeGroup name="password-compare.attlist">
|
||||
<xs:attribute name="password-attribute" type="xs:string">
|
||||
|
|
|
@ -7,6 +7,8 @@ import org.springframework.security.util.AuthorityUtils;
|
|||
import org.springframework.security.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.userdetails.UserDetailsService;
|
||||
import org.springframework.security.userdetails.UserDetails;
|
||||
import org.springframework.security.userdetails.ldap.InetOrgPerson;
|
||||
import org.springframework.security.userdetails.ldap.Person;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.After;
|
||||
|
@ -99,7 +101,28 @@ public class LdapUserServiceBeanDefinitionParserTests {
|
|||
" <ldap-user-service user-search-filter='(uid={0})' />" +
|
||||
"</authentication-provider>");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void personContextMapperIsSupported() {
|
||||
setContext(
|
||||
"<ldap-server />" +
|
||||
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='person'/>");
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertTrue(ben instanceof Person);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inetOrgContextMapperIsSupported() {
|
||||
setContext(
|
||||
"<ldap-server id='someServer'/>" +
|
||||
"<ldap-user-service id='ldapUDS' user-search-filter='(uid={0})' user-details-class='inetOrgPerson'/>");
|
||||
UserDetailsService uds = (UserDetailsService) appCtx.getBean("ldapUDS");
|
||||
UserDetails ben = uds.loadUserByUsername("ben");
|
||||
assertTrue(ben instanceof InetOrgPerson);
|
||||
}
|
||||
|
||||
|
||||
private void setContext(String context) {
|
||||
appCtx = new InMemoryXmlApplicationContext(context);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue