From c658efbc69cf0fcf54006fdbe737df3b67cdf445 Mon Sep 17 00:00:00 2001 From: Vishal Puri Date: Mon, 2 Jul 2007 07:54:59 +0000 Subject: [PATCH] SEC-271: added ldap authentication parser --- sandbox/spring-security-config/.classpath | 4 +- sandbox/spring-security-config/.project | 46 ++++++------ ....eclipse.wst.common.project.facet.core.xml | 2 +- ...ticationMechanismBeanDefinitionParser.java | 65 ++++++++++++++-- .../util/BeanDefinitionParserUtils.java | 42 +++++++++++ .../config/spring-security-2.0.xsd | 75 ++++++++++++++++--- ...tionProviderBeanDefinitionParserTests.java | 52 +++++++++++++ .../authentication-beanRef-attributes.xml | 2 - ...ception-translation-autodetect-handler.xml | 2 - .../org/acegisecurity/config/ldap-config.xml | 73 ++++++++++++++++++ .../config/principal-repository-jdbc.xml | 2 - 11 files changed, 315 insertions(+), 50 deletions(-) create mode 100644 sandbox/spring-security-config/src/main/java/org/acegisecurity/util/BeanDefinitionParserUtils.java create mode 100644 sandbox/spring-security-config/src/test/java/org/acegisecurity/config/LdapAuthenticationProviderBeanDefinitionParserTests.java create mode 100644 sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/ldap-config.xml diff --git a/sandbox/spring-security-config/.classpath b/sandbox/spring-security-config/.classpath index c078c92989..a855ebb353 100644 --- a/sandbox/spring-security-config/.classpath +++ b/sandbox/spring-security-config/.classpath @@ -7,7 +7,7 @@ - + @@ -39,6 +39,6 @@ - + diff --git a/sandbox/spring-security-config/.project b/sandbox/spring-security-config/.project index 1e65037c34..2539d6ea37 100644 --- a/sandbox/spring-security-config/.project +++ b/sandbox/spring-security-config/.project @@ -1,23 +1,25 @@ + - spring-security-config - Acegi Security System for Spring - - - - org.eclipse.jdt.core.javabuilder - - - org.eclipse.wst.validation.validationbuilder - - - org.springframework.ide.eclipse.core.springbuilder - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jem.workbench.JavaEMFNature - - \ No newline at end of file + spring-security-config + Acegi Security System for Spring + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + + diff --git a/sandbox/spring-security-config/.settings/org.eclipse.wst.common.project.facet.core.xml b/sandbox/spring-security-config/.settings/org.eclipse.wst.common.project.facet.core.xml index de06d14c18..9bbcbd78eb 100644 --- a/sandbox/spring-security-config/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/sandbox/spring-security-config/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/sandbox/spring-security-config/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java b/sandbox/spring-security-config/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java index 13a68ed377..ad9a0915b6 100644 --- a/sandbox/spring-security-config/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java +++ b/sandbox/spring-security-config/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java @@ -13,7 +13,13 @@ * limitations under the License. */ package org.acegisecurity.config; + +import org.acegisecurity.ldap.DefaultInitialDirContextFactory; import org.acegisecurity.providers.ProviderManager; +import org.acegisecurity.providers.ldap.LdapAuthenticationProvider; +import org.acegisecurity.providers.ldap.authenticator.BindAuthenticator; +import org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator; +import org.acegisecurity.util.BeanDefinitionParserUtils; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.ManagedList; @@ -23,14 +29,15 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** - * * {@link BeanDefinitionParser} for the authentication-mechanism tag, - * resolves to {@link org.acegisecurity.providers.ProviderManager}
- + * * {@link BeanDefinitionParser} for the authentication-mechanism + * tag, resolves to {@link org.acegisecurity.providers.ProviderManager}
+ * * @author vpuri * @see {@link org.springframework.beans.factory.BeanFactory} * @see {@link org.acegisecurity.providers.ProviderManager} @@ -42,6 +49,8 @@ public class AuthenticationMechanismBeanDefinitionParser extends AbstractBeanDef // ================================================================================================ private static final String AUTHENTICATION_JDBC = "authentication-jdbc"; + + private static final String AUTHENTICATION_LDAP="authentication-ldap"; private static final String REF = "ref"; @@ -59,7 +68,7 @@ public class AuthenticationMechanismBeanDefinitionParser extends AbstractBeanDef if (node.getNodeType() == Node.ELEMENT_NODE) { Element childElement = (Element) node; - //this.providerExists = true; + // this.providerExists = true; if (AUTHENTICATION_JDBC.equals(node.getLocalName())) { String attribute = childElement.getAttribute(REF); @@ -67,15 +76,16 @@ public class AuthenticationMechanismBeanDefinitionParser extends AbstractBeanDef // create a beandefinition providers.add(new RuntimeBeanReference(attribute)); } - + } else if (AUTHENTICATION_LDAP.equals(node.getLocalName())){ + providers.add(createLdapAuthencticationProviderBeanDefinition(childElement, parserContext)); } - // TODO:Add other providers here } authMechanismBeanDef.getPropertyValues().addPropertyValue("providers", providers); } return authMechanismBeanDef; } + /** * Creates a default bean definition. * @return @@ -83,12 +93,51 @@ public class AuthenticationMechanismBeanDefinitionParser extends AbstractBeanDef protected static RootBeanDefinition createAndRegisterBeanDefinitionWithDefaults(ParserContext parserContext) { RootBeanDefinition beanDefinition = new RootBeanDefinition(ProviderManager.class); ManagedList providers = new ManagedList(); - // create authentication-repository (DaoAuthenticationProvider) and add that to list + // create authentication-repository (DaoAuthenticationProvider) and add + // that to list RootBeanDefinition authRepo = AuthenticationRepositoryBeanDefinitionParser.createBeanDefinitionWithDefaults(); providers.add(authRepo); beanDefinition.getPropertyValues().addPropertyValue("providers", providers); parserContext.getReaderContext().registerWithGeneratedName(beanDefinition); return beanDefinition; } - + + protected static RootBeanDefinition createLdapAuthencticationProviderBeanDefinition(Element element, + ParserContext parserContext) { + // element ldap + RootBeanDefinition ldapAuthProvider = new RootBeanDefinition(LdapAuthenticationProvider.class); + RootBeanDefinition initialDirContextFactory = createInitialDirContextFactoryBeanDefinition(element); + RootBeanDefinition ldapAuthoritiesPopulator = new RootBeanDefinition(DefaultLdapAuthoritiesPopulator.class); + + RootBeanDefinition bindAuthenticator = new RootBeanDefinition(BindAuthenticator.class); + Element property = DomUtils.getChildElementByTagName(element, "property"); + Assert.notNull(property); + parserContext.getDelegate().parsePropertyElement(property, bindAuthenticator); + bindAuthenticator.getConstructorArgumentValues().addIndexedArgumentValue(0, initialDirContextFactory); + + // LdapAuthenticator + ldapAuthProvider.getConstructorArgumentValues().addIndexedArgumentValue(0, bindAuthenticator); + + ldapAuthoritiesPopulator.getConstructorArgumentValues().addIndexedArgumentValue(0, initialDirContextFactory); + BeanDefinitionParserUtils.setConstructorArgumentIfAvailable(1, element, "groupSearchBase", false, + ldapAuthoritiesPopulator); + BeanDefinitionParserUtils.setPropertyIfAvailable(element, "groupRoleAttribute", "groupRoleAttribute", ldapAuthoritiesPopulator); + + //LdapAuthoritiesPopulator + ldapAuthProvider.getConstructorArgumentValues().addIndexedArgumentValue(1, ldapAuthoritiesPopulator); + + return ldapAuthProvider; + + } + + private static RootBeanDefinition createInitialDirContextFactoryBeanDefinition(Element element) { + RootBeanDefinition initialDirContextFactory = new RootBeanDefinition(DefaultInitialDirContextFactory.class); + BeanDefinitionParserUtils.setConstructorArgumentIfAvailable(0, element, "ldapUrl", false, + initialDirContextFactory); + BeanDefinitionParserUtils.setPropertyIfAvailable(element, "managerDn", "managerDn", initialDirContextFactory); + BeanDefinitionParserUtils.setPropertyIfAvailable(element, "managerPassword", "managerPassword", + initialDirContextFactory); + return initialDirContextFactory; + } + } diff --git a/sandbox/spring-security-config/src/main/java/org/acegisecurity/util/BeanDefinitionParserUtils.java b/sandbox/spring-security-config/src/main/java/org/acegisecurity/util/BeanDefinitionParserUtils.java new file mode 100644 index 0000000000..a5e599d159 --- /dev/null +++ b/sandbox/spring-security-config/src/main/java/org/acegisecurity/util/BeanDefinitionParserUtils.java @@ -0,0 +1,42 @@ +/** + * + */ +package org.acegisecurity.util; + +import org.springframework.beans.factory.config.RuntimeBeanNameReference; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +/** + * @author Vishal Puri + * + */ +public class BeanDefinitionParserUtils { + /** + * Prevents instantiation + */ + private BeanDefinitionParserUtils() { + } + + public static void setConstructorArgumentIfAvailable(int index, Element element, String attribute, + boolean isRunTimeBeanReference, RootBeanDefinition definition) { + String propertyValue = element.getAttribute(attribute); + if (StringUtils.hasText(propertyValue)) { + if(!isRunTimeBeanReference){ + definition.getConstructorArgumentValues().addIndexedArgumentValue(index, propertyValue); + } else { + definition.getConstructorArgumentValues().addIndexedArgumentValue(index, new RuntimeBeanNameReference(propertyValue)); + } + } + } + + public static void setPropertyIfAvailable(Element element, String attribute, String property, + RootBeanDefinition definition) { + String propertyValue = element.getAttribute(attribute); + if (StringUtils.hasText(propertyValue)) { + definition.getPropertyValues().addPropertyValue(property, propertyValue); + } + } +} diff --git a/sandbox/spring-security-config/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd b/sandbox/spring-security-config/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd index edf437da20..1fcb0d6f4d 100644 --- a/sandbox/spring-security-config/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd +++ b/sandbox/spring-security-config/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd @@ -3,11 +3,13 @@ - - - - + + + + + @@ -88,13 +90,14 @@ - - + - - - + + + @@ -289,12 +292,61 @@ ]]> + - + + + + + + + + + + + + " element. + The LDAP url of the server (and root context) to connect to. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -475,4 +527,5 @@ + \ No newline at end of file diff --git a/sandbox/spring-security-config/src/test/java/org/acegisecurity/config/LdapAuthenticationProviderBeanDefinitionParserTests.java b/sandbox/spring-security-config/src/test/java/org/acegisecurity/config/LdapAuthenticationProviderBeanDefinitionParserTests.java new file mode 100644 index 0000000000..3e3c267f4f --- /dev/null +++ b/sandbox/spring-security-config/src/test/java/org/acegisecurity/config/LdapAuthenticationProviderBeanDefinitionParserTests.java @@ -0,0 +1,52 @@ +package org.acegisecurity.config; + +import junit.framework.TestCase; + +import org.acegisecurity.ldap.InitialDirContextFactory; +import org.acegisecurity.providers.ldap.LdapAuthenticationProvider; +import org.acegisecurity.providers.ldap.authenticator.BindAuthenticator; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author Vishal Puri + * + */ +public class LdapAuthenticationProviderBeanDefinitionParserTests extends TestCase { + + public void testBeanDefinitionCreation() { + ApplicationContext context = new ClassPathXmlApplicationContext("org/acegisecurity/config/ldap-config.xml"); + ConfigurableListableBeanFactory bf = (ConfigurableListableBeanFactory) context.getAutowireCapableBeanFactory(); + BeanDefinition def = (RootBeanDefinition) bf.getBeanDefinition("authenticationManager"); + assertNotNull(def); + PropertyValues values = def.getPropertyValues(); + PropertyValue value = values.getPropertyValue("providers"); + assertNotNull(value); + ManagedList list = (ManagedList) value.getValue(); + assertEquals(1, list.size()); + + RootBeanDefinition definition = (RootBeanDefinition) list.get(0); + assertEquals(LdapAuthenticationProvider.class, definition.getBeanClass()); + + assertEquals(2, definition.getConstructorArgumentValues().getArgumentCount()); + + ValueHolder holder = definition.getConstructorArgumentValues().getArgumentValue(0, BindAuthenticator.class); + assertNotNull(holder.getConvertedValue() instanceof BindAuthenticator); + RootBeanDefinition authenticatorDefinition = (RootBeanDefinition) holder.getValue(); + assertEquals(1, authenticatorDefinition.getConstructorArgumentValues().getArgumentCount()); + + RootBeanDefinition initialContextDir = (RootBeanDefinition) authenticatorDefinition + .getConstructorArgumentValues().getArgumentValue(0, InitialDirContextFactory.class).getValue(); + assertEquals("cn=manager,dc=acegisecurity,dc=org", initialContextDir.getPropertyValues().getPropertyValue( + "managerDn").getValue()); + assertEquals("ldap://monkeymachine:389/dc=acegisecurity,dc=org", initialContextDir.getConstructorArgumentValues() + .getArgumentValue(0, String.class).getValue()); + } +} diff --git a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/authentication-beanRef-attributes.xml b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/authentication-beanRef-attributes.xml index 43b4967648..9885cdf1dc 100644 --- a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/authentication-beanRef-attributes.xml +++ b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/authentication-beanRef-attributes.xml @@ -3,9 +3,7 @@ diff --git a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/exception-translation-autodetect-handler.xml b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/exception-translation-autodetect-handler.xml index 7710ca156d..9c927be891 100644 --- a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/exception-translation-autodetect-handler.xml +++ b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/exception-translation-autodetect-handler.xml @@ -3,9 +3,7 @@ diff --git a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/ldap-config.xml b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/ldap-config.xml new file mode 100644 index 0000000000..c73468314d --- /dev/null +++ b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/ldap-config.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + uid={0},ou=people + + + + + + + + + \ No newline at end of file diff --git a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/principal-repository-jdbc.xml b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/principal-repository-jdbc.xml index 543b986f32..7172f5f919 100644 --- a/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/principal-repository-jdbc.xml +++ b/sandbox/spring-security-config/src/test/resources/org/acegisecurity/config/principal-repository-jdbc.xml @@ -3,9 +3,7 @@