diff --git a/core/src/main/java/org/springframework/security/config/BeanIds.java b/core/src/main/java/org/springframework/security/config/BeanIds.java index a18f5b00ad..020f90b0fa 100644 --- a/core/src/main/java/org/springframework/security/config/BeanIds.java +++ b/core/src/main/java/org/springframework/security/config/BeanIds.java @@ -11,7 +11,7 @@ public abstract class BeanIds { /** Package protected as end users shouldn't really be using this BFPP directly */ static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP"; static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor"; - static final String HTTP_POST_PROCESSOR = "_httpConfigBeanFactoryPostProcessor"; + static final String HTTP_POST_PROCESSOR = "_httpConfigBeanFactoryPostProcessor"; public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager"; public static final String USER_DETAILS_SERVICE = "_userDetailsService"; @@ -43,5 +43,5 @@ public abstract class BeanIds { public static final String METHOD_DEFINITION_ATTRIBUTES = "_methodDefinitionAttributes"; public static final String EMBEDDED_APACHE_DS = "_apacheDirectoryServerContainer"; public static final String CONTEXT_SOURCE = "_securityContextSource"; - public static final String PORT_MAPPER = "_portMapper"; + public static final String PORT_MAPPER = "_portMapper"; } diff --git a/core/src/main/java/org/springframework/security/config/UserServiceBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/UserServiceBeanDefinitionParser.java index a5fa4e7f18..cea8c76d6b 100644 --- a/core/src/main/java/org/springframework/security/config/UserServiceBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/UserServiceBeanDefinitionParser.java @@ -1,10 +1,16 @@ package org.springframework.security.config; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.security.userdetails.memory.InMemoryDaoImpl; import org.springframework.security.userdetails.memory.UserMap; import org.springframework.security.userdetails.User; import org.springframework.security.util.AuthorityUtils; +import org.springframework.util.StringUtils; +import org.springframework.util.Assert; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -22,13 +28,30 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB static final String ATT_NAME = "name"; static final String ELT_USER = "user"; static final String ATT_AUTHORITIES = "authorities"; + static final String ATT_PROPERTIES = "properties"; protected Class getBeanClass(Element element) { return InMemoryDaoImpl.class; } protected void doParse(Element element, BeanDefinitionBuilder builder) { + String userProperties = element.getAttribute(ATT_PROPERTIES); List userElts = DomUtils.getChildElementsByTagName(element, ELT_USER); + + if (StringUtils.hasText(userProperties)) { + Assert.isTrue(userElts.isEmpty(), "Use of a properties file ('" + ATT_PROPERTIES + "' attribute) and <" + + ELT_USER + "> elements are mutually exclusive."); + + BeanDefinition bd = new RootBeanDefinition(PropertiesFactoryBean.class); + bd.getPropertyValues().addPropertyValue("location", userProperties); + builder.addPropertyValue("userProperties", bd); + + return; + } + + Assert.notEmpty(userElts, "You must supply user definitions, either with <" + ELT_USER + "> child elements or a " + + "properties file (specified with the '" + ATT_PROPERTIES + "' attribute)" ); + UserMap users = new UserMap(); for (Iterator i = userElts.iterator(); i.hasNext();) { diff --git a/core/src/test/java/org/springframework/security/config/UserServiceBeanDefinitionParserTests.java b/core/src/test/java/org/springframework/security/config/UserServiceBeanDefinitionParserTests.java new file mode 100644 index 0000000000..cdc687c561 --- /dev/null +++ b/core/src/test/java/org/springframework/security/config/UserServiceBeanDefinitionParserTests.java @@ -0,0 +1,71 @@ +package org.springframework.security.config; + +import org.springframework.security.util.InMemoryXmlApplicationContext; +import org.springframework.security.userdetails.UserDetailsService; +import org.springframework.context.support.AbstractXmlApplicationContext; +import org.springframework.beans.FatalBeanException; + +import org.junit.Test; +import org.junit.After; + +/** + * @author Luke Taylor + * @version $Id$ + */ +public class UserServiceBeanDefinitionParserTests { + private AbstractXmlApplicationContext appContext; + + @After + public void closeAppContext() { + if (appContext != null) { + appContext.close(); + } + } + + @Test + public void userServiceWithValidPropertiesFileWorksSuccessfully() { + setContext( + ""); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); + userService.loadUserByUsername("bob"); + userService.loadUserByUsername("joe"); + } + + @Test + public void userServiceWithEmbeddedUsersWorksSuccessfully() { + setContext( + "" + + " " + + ""); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); + userService.loadUserByUsername("joe"); + } + + @Test(expected=FatalBeanException.class) + public void userWithBothPropertiesAndEmbeddedUsersThrowsException() { + setContext( + "" + + " " + + ""); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); + userService.loadUserByUsername("joe"); + } + + @Test(expected= FatalBeanException.class) + public void multipleTopLevelUseWithoutIdThrowsException() { + setContext( + "" + + ""); + + } + + @Test(expected= FatalBeanException.class) + public void userServiceWithMissingPropertiesFileThrowsException() { + setContext(""); + } + + private void setContext(String context) { + appContext = new InMemoryXmlApplicationContext(context); + } +} diff --git a/core/src/test/resources/org/springframework/security/config/users.properties b/core/src/test/resources/org/springframework/security/config/users.properties new file mode 100644 index 0000000000..d2369d9a08 --- /dev/null +++ b/core/src/test/resources/org/springframework/security/config/users.properties @@ -0,0 +1,2 @@ +joe=joespassword,ROLE_A +bob=bobspassword,ROLE_A,ROLE_B