diff --git a/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java index 2bf33c6aa0..83cea52e75 100644 --- a/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParser.java @@ -14,6 +14,8 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.List; import java.util.Iterator; @@ -32,6 +34,8 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB static final String ATT_DISABLED = "disabled"; static final String ATT_LOCKED = "locked"; + private SecureRandom random; + protected String getBeanClassName(Element element) { return "org.springframework.security.core.userdetails.memory.InMemoryDaoImpl"; } @@ -65,6 +69,11 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB Element userElt = (Element) i.next(); String userName = userElt.getAttribute(ATT_NAME); String password = userElt.getAttribute(ATT_PASSWORD); + + if (!StringUtils.hasLength(password)) { + password = generateRandomPassword(); + } + boolean locked = "true".equals(userElt.getAttribute(ATT_LOCKED)); boolean disabled = "true".equals(userElt.getAttribute(ATT_DISABLED)); @@ -74,4 +83,16 @@ public class UserServiceBeanDefinitionParser extends AbstractUserDetailsServiceB builder.addPropertyValue("userMap", users); } + + private String generateRandomPassword() { + if (random == null) { + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + // Shouldn't happen... + throw new RuntimeException("Failed find SHA1PRNG algorithm!"); + } + } + return Long.toString(random.nextLong()); + } } diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc index 53639277c6..0f751cf3f0 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc @@ -533,7 +533,7 @@ x509.attlist &= user-service-ref? authentication-manager = - ## Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. should use. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans. + ## Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans. element authentication-manager {authman.attlist & authentication-provider* & ldap-authentication-provider*} authman.attlist &= ## The alias you wish to use for the AuthenticationManager bean @@ -562,8 +562,8 @@ user.attlist &= ## The username assigned to the user. attribute name {xsd:token} user.attlist &= - ## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). - attribute password {xsd:string} + ## The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty. + attribute password {xsd:string}? user.attlist &= ## One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" attribute authorities {xsd:token} diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd index c3159594cb..de2df47956 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd @@ -1096,7 +1096,7 @@ - Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. should use. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans. + Registers the AuthenticationManager instance and allows its list of AuthenticationProviders to be defined. Also allows you to define an alias to allow you to reference the AuthenticationManager in your own beans. @@ -1223,9 +1223,9 @@ The username assigned to the user. - + - The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). + The password assigned to the user. This may be hashed if the corresponding authentication provider supports hashing (remember to set the "hash" attribute of the "user-service" element). This attribute be omitted in the case where the data will not be used for authentication, but only for accessing authorities. If omitted, the namespace will generate a random value, preventing its accidental use for authentication. Cannot be empty. diff --git a/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java index 0e0993e02c..803b2a6abd 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/UserServiceBeanDefinitionParserTests.java @@ -45,6 +45,18 @@ public class UserServiceBeanDefinitionParserTests { userService.loadUserByUsername("joe"); } + @Test + public void embeddedUsersWithNoPasswordIsGivenGeneratedValue() { + setContext( + "" + + " " + + ""); + UserDetailsService userService = (UserDetailsService) appContext.getBean("service"); + UserDetails joe = userService.loadUserByUsername("joe"); + assertTrue(joe.getPassword().length() > 0); + Long.parseLong(joe.getPassword()); + } + @Test public void disabledAndEmbeddedFlagsAreSupported() { setContext( @@ -58,8 +70,8 @@ public class UserServiceBeanDefinitionParserTests { UserDetails bob = userService.loadUserByUsername("bob"); assertFalse(bob.isEnabled()); } - - + + @Test(expected=FatalBeanException.class) public void userWithBothPropertiesAndEmbeddedUsersThrowsException() { setContext( diff --git a/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml b/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml index b3924120fc..a629d6cd5c 100644 --- a/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml +++ b/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml @@ -27,10 +27,10 @@ - - - - + + + +