2
0
Эх сурвалжийг харах

added new security element in the spring-security schema and wrote a parser for the element

Vishal Puri 18 жил өмнө
parent
commit
ced5cb4f85

+ 76 - 0
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;
+
+	}
+}

+ 41 - 0
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;
+	}
+
+	
+}

+ 76 - 0
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));
+		}
+	}
+
+
+
+}

+ 1 - 1
core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd

@@ -183,7 +183,7 @@
 		<xsd:complexType>
 			<xsd:attribute name="dataSourceBeanRef" type="xsd:string" />
 			<xsd:attribute name="authoritiesByUsernameQuery" type="xsd:string" use="optional"/>
-			<xsd:attribute name="jdbcTemplateRef" type="xsd:string" use="optional"/>
+			<xsd:attribute name="jdbcTemplateBeanRef" type="xsd:string" use="optional"/>
 			<xsd:attribute name="rolePrefix" type="xsd:string" use="optional"/>
 			<xsd:attribute name="usernameBasedPrimaryKey" type="xsd:boolean" use="optional"/>
 			<xsd:attribute name="usersByUsernameQuery" type="xsd:string" use="optional"/>

+ 3 - 1
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");
+		
+		
 	}
 
 }

+ 42 - 0
core/src/test/resources/org/acegisecurity/config/principal-repository.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:security="http://www.springframework.org/schema/security"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
+	http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-2.0.xsd
+http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd">
+
+	<!-- http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd -->
+	<!-- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd" -->
+
+	<!-- userDetailsService, This is used if they want an out-of-the-bx UserDetailsService; if they write their own, this goes away and they wire a legacy bean definition and then the various
+		beans depending on a UserDetailsService will auto-detect it at runtime OR provide a way of setUserDetailsService(UserDetailsService) if to specified explicitly.
+		If they fail to provide a repository, the security-autodetect will set one up for them with a few basic in-memory users and pwds -->
+	<security:principal-repository id="userDetailsService">
+		<security:jdbc dataSourceBeanRef="dataSource" jdbcTemplateBeanRef="jdbcTemplate" authoritiesByUsernameQuery=""  rolePrefix="" usernameBasedPrimaryKey="true"  usersByUsernameQuery=""/>
+	</security:principal-repository>
+
+	<bean id="dataSource"
+		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+		<property name="driverClassName">
+			<value>org.hsqldb.jdbcDriver</value>
+		</property>
+		<property name="url">
+			<value>jdbc:hsqldb:mem:test</value>
+			<!-- <value>jdbc:hsqldb:hsql://localhost/acl</value> -->
+		</property>
+		<property name="username">
+			<value>sa</value>
+		</property>
+		<property name="password">
+			<value></value>
+		</property>
+	</bean>
+	
+	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+		<property name="dataSource" ref="dataSource"></property>
+	</bean>
+
+</beans>

+ 1 - 0
pom.xml

@@ -461,6 +461,7 @@
 				<scope>runtime</scope>
 			</dependency>
 		</dependencies>
+		
 	</dependencyManagement>
 	<properties>
 		<spring.version>2.0.4</spring.version>