From ced5cb4f851129f7c7bff76e7b6d4a1428edc5d1 Mon Sep 17 00:00:00 2001 From: Vishal Puri Date: Sun, 13 May 2007 13:33:33 +0000 Subject: [PATCH] added new security element in the spring-security schema and wrote a parser for the element --- ...ticationMechanismBeanDefinitionParser.java | 76 +++++++++++++++++++ .../AuthenticationProviderOrderResolver.java | 41 ++++++++++ ...incipalRepositoryBeanDefinitionParser.java | 76 +++++++++++++++++++ .../config/spring-security-2.0.xsd | 2 +- .../RememberMeBeanDefinitionParserTest.java | 4 +- .../config/principal-repository.xml | 42 ++++++++++ pom.xml | 1 + 7 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java create mode 100644 core/src/main/java/org/acegisecurity/config/AuthenticationProviderOrderResolver.java create mode 100644 core/src/main/java/org/acegisecurity/config/PrincipalRepositoryBeanDefinitionParser.java create mode 100644 core/src/test/resources/org/acegisecurity/config/principal-repository.xml diff --git a/core/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java b/core/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java new file mode 100644 index 0000000000..af61ce778a --- /dev/null +++ b/core/src/main/java/org/acegisecurity/config/AuthenticationMechanismBeanDefinitionParser.java @@ -0,0 +1,76 @@ +/** + * + */ +package org.acegisecurity.config; + +import java.util.ArrayList; +import java.util.List; + +import org.acegisecurity.providers.ProviderManager; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +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.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author vpuri + * + */ +public class AuthenticationMechanismBeanDefinitionParser extends AbstractBeanDefinitionParser implements + BeanDefinitionParser { + + private static final Object AUTHENTICATION_JDBC = "authentication-jdbc"; + + private static final String REF = "ref"; + + private boolean providerExists = false; + + + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + + ManagedList providers = new ManagedList(); + Assert.notNull(parserContext, "ParserContext must not be null"); + RootBeanDefinition authMechanismBeanDef = new RootBeanDefinition(ProviderManager.class); + NodeList childNodes = element.getChildNodes(); + + for (int i = 0, n = childNodes.getLength(); i < n; i++) { + Node node = childNodes.item(i); + + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element childElement = (Element) node; + providerExists = true; + + if (AUTHENTICATION_JDBC.equals(node.getLocalName())) { + String attribute = childElement.getAttribute(REF); + if (StringUtils.hasLength(attribute)) { + // create a beandefinition + providers.add(new RuntimeBeanReference(attribute)); + } + + } + // TODO:Add other providers here + } + authMechanismBeanDef.getPropertyValues().addPropertyValue("providers", providers); + + } + + if (!providerExists) { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(AuthenticationProviderOrderResolver.class); + BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(rootBeanDefinition, + "providerOrderResolver"); + registerBeanDefinition(beanDefinitionHolder, parserContext.getRegistry()); + } + + return authMechanismBeanDef; + + } +} diff --git a/core/src/main/java/org/acegisecurity/config/AuthenticationProviderOrderResolver.java b/core/src/main/java/org/acegisecurity/config/AuthenticationProviderOrderResolver.java new file mode 100644 index 0000000000..938c2b8a20 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/config/AuthenticationProviderOrderResolver.java @@ -0,0 +1,41 @@ +package org.acegisecurity.config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.acegisecurity.AuthenticationManager; +import org.acegisecurity.providers.AuthenticationProvider; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.core.OrderComparator; + +public class AuthenticationProviderOrderResolver implements BeanFactoryPostProcessor { + + /** + * + */ + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + // retrieve all the AuthenticationProvider instances + List providers = retrieveAllAuthenticationProviders(beanFactory); + String[] names = beanFactory.getBeanNamesForType(AuthenticationManager.class); + RootBeanDefinition definition = (RootBeanDefinition)beanFactory.getBeanDefinition(names[0]); + definition.getPropertyValues().addPropertyValue("providers",providers); + } + /** + * + * @param beanFactory + * @return + */ + private List retrieveAllAuthenticationProviders(ConfigurableListableBeanFactory beanFactory) { + Map m = beanFactory.getBeansOfType(AuthenticationProvider.class); + List l = new ArrayList(m.values()); + Collections.sort(l, new OrderComparator()); + return l; + } + + +} diff --git a/core/src/main/java/org/acegisecurity/config/PrincipalRepositoryBeanDefinitionParser.java b/core/src/main/java/org/acegisecurity/config/PrincipalRepositoryBeanDefinitionParser.java new file mode 100644 index 0000000000..93e6395b37 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/config/PrincipalRepositoryBeanDefinitionParser.java @@ -0,0 +1,76 @@ +/** + * + */ +package org.acegisecurity.config; + +import org.acegisecurity.userdetails.jdbc.JdbcDaoImpl; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author vpuri + * + */ +public class PrincipalRepositoryBeanDefinitionParser extends AbstractBeanDefinitionParser implements + BeanDefinitionParser { + + // ~ Instance fields ================================================================================================ + private static final String JDBC = "jdbc"; + private static final String DATASOURCE_REF = "dataSourceBeanRef"; + private static final String DATASOURCE = "dataSource"; + private static final String JDBCTEMPLATE_REF = "jdbcTemplateBeanRef"; + private static final String JDBCTEMPLATE = "jdbcTemplate"; + private static final String AUTHORITIES_BY_USERNAME_QUERY = "authoritiesByUsernameQuery"; + private static final String ROLE_PREFIX = "rolePrefix"; + private static final String USERNAME_BASED_PRIMARY_KEY="usernameBasedPrimaryKey"; + + //authoritiesByUsernameQuery="" rolePrefix="" usernameBasedPrimaryKey="true" usersByUsernameQuery="" + + // ~ Method ================================================================================================ + + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + + NodeList userDetailsServiceChildren = element.getChildNodes(); + RootBeanDefinition userDetailsServiceJdbcDefinition = null; + for (int i = 0, n = userDetailsServiceChildren.getLength(); i < n; i++) { + Node userDetailsService = userDetailsServiceChildren.item(i); + + if (JDBC.equals(userDetailsService.getLocalName()) && userDetailsService.getNodeType() == Node.ELEMENT_NODE) { + Element ele = (Element) userDetailsService; + userDetailsServiceJdbcDefinition = parseUserDetailsServiceJdbcDefinition(ele); + userDetailsServiceJdbcDefinition.setSource(parserContext.extractSource(element)); + parserContext.getReaderContext().registerWithGeneratedName(userDetailsServiceJdbcDefinition); + } + } + return userDetailsServiceJdbcDefinition; + } + + private RootBeanDefinition parseUserDetailsServiceJdbcDefinition(Element elementToParse) { + // parse attributes + RootBeanDefinition definition = new RootBeanDefinition(JdbcDaoImpl.class); + setPropertyIfAvailable(elementToParse, DATASOURCE_REF, DATASOURCE, definition); + setPropertyIfAvailable(elementToParse, JDBCTEMPLATE_REF, JDBCTEMPLATE, definition); + setPropertyIfAvailable(elementToParse, AUTHORITIES_BY_USERNAME_QUERY, AUTHORITIES_BY_USERNAME_QUERY, definition); + setPropertyIfAvailable(elementToParse, ROLE_PREFIX, ROLE_PREFIX, definition); + setPropertyIfAvailable(elementToParse, USERNAME_BASED_PRIMARY_KEY, USERNAME_BASED_PRIMARY_KEY, definition); + return definition; + } + + private void setPropertyIfAvailable(Element el, String attribute, String property, RootBeanDefinition definition) { + String propertyValue = el.getAttribute(attribute); + if (StringUtils.hasText(propertyValue)) { + definition.getPropertyValues().addPropertyValue(property, new RuntimeBeanReference(propertyValue)); + } + } + + + +} diff --git a/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd b/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd index 7aeb607ffc..13cd41f94f 100644 --- a/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd +++ b/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd @@ -183,7 +183,7 @@ - + diff --git a/core/src/test/java/org/acegisecurity/config/RememberMeBeanDefinitionParserTest.java b/core/src/test/java/org/acegisecurity/config/RememberMeBeanDefinitionParserTest.java index b9d82b8633..e0ab90af94 100644 --- a/core/src/test/java/org/acegisecurity/config/RememberMeBeanDefinitionParserTest.java +++ b/core/src/test/java/org/acegisecurity/config/RememberMeBeanDefinitionParserTest.java @@ -8,7 +8,9 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class RememberMeBeanDefinitionParserTest extends TestCase { public void testRememberMeDefaults() { - ApplicationContext context = new ClassPathXmlApplicationContext("org/acegisecurity/config/principal-defaults.xml"); + ApplicationContext context = new ClassPathXmlApplicationContext("org/acegisecurity/config/remember-me-defaults.xml"); + + } } diff --git a/core/src/test/resources/org/acegisecurity/config/principal-repository.xml b/core/src/test/resources/org/acegisecurity/config/principal-repository.xml new file mode 100644 index 0000000000..d417826faf --- /dev/null +++ b/core/src/test/resources/org/acegisecurity/config/principal-repository.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + org.hsqldb.jdbcDriver + + + jdbc:hsqldb:mem:test + + + + sa + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index f643b319d1..5a7d68bf4d 100644 --- a/pom.xml +++ b/pom.xml @@ -461,6 +461,7 @@ runtime + 2.0.4