From 8c3cc5c67b62bb5289554bcc04e5d86455d6f1d4 Mon Sep 17 00:00:00 2001 From: Ben Alex Date: Tue, 4 Dec 2007 11:21:39 +0000 Subject: [PATCH] Add hash code support. --- .../RepositoryBeanDefinitionParser.java | 53 +++++++++-- .../security/config/spring-security-2.0.rnc | 15 ++++ .../security/config/spring-security-2.0.xsd | 90 ++++++++++++++++++- .../applicationContext-security-ns.xml | 19 ++-- 4 files changed, 158 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/springframework/security/config/RepositoryBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/RepositoryBeanDefinitionParser.java index 07279d0526..e0d1225fee 100644 --- a/core/src/main/java/org/springframework/security/config/RepositoryBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/RepositoryBeanDefinitionParser.java @@ -6,6 +6,11 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.security.providers.dao.DaoAuthenticationProvider; +import org.springframework.security.providers.encoding.Md4PasswordEncoder; +import org.springframework.security.providers.encoding.Md5PasswordEncoder; +import org.springframework.security.providers.encoding.PasswordEncoder; +import org.springframework.security.providers.encoding.PlaintextPasswordEncoder; +import org.springframework.security.providers.encoding.ShaPasswordEncoder; import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -21,10 +26,20 @@ import org.w3c.dom.Element; */ class RepositoryBeanDefinitionParser implements BeanDefinitionParser { - static final String ATT_CREATE_PROVIDER = "createProvider"; static final String ATT_DATA_SOURCE = "dataSource"; static final String ATT_ID = "id"; + + static final String ATT_CREATE_PROVIDER = "createProvider"; static final String DEF_CREATE_PROVIDER = "true"; + + static final String ATT_HASH = "hash"; + static final String DEF_HASH_PLAINTEXT = "plaintext"; + static final String OPT_HASH_SHA_HEX = "sha:hex"; + static final String OPT_HASH_SHA_BASE64 = "sha:base64"; + static final String OPT_HASH_MD4_HEX = "md4:hex"; + static final String OPT_HASH_MD4_BASE64 = "md4:base64"; + static final String OPT_HASH_MD5_HEX = "md5:hex"; + static final String OPT_HASH_MD5_BASE64 = "md5:base64"; public BeanDefinition parse(Element element, ParserContext parserContext) { boolean createProvider = true; @@ -43,7 +58,7 @@ class RepositoryBeanDefinitionParser implements BeanDefinitionParser { if (userServiceElt != null) { BeanDefinition userDetailsService = new UserServiceBeanDefinitionParser().parse(userServiceElt, parserContext); - createDaoAuthenticationProviderIfRequired(createProvider, userDetailsService, parserContext); + createDaoAuthenticationProviderIfRequired(createProvider, userServiceElt.getAttribute(ATT_HASH), userDetailsService, parserContext); } if (jdbcUserServiceElt != null) { @@ -54,22 +69,50 @@ class RepositoryBeanDefinitionParser implements BeanDefinitionParser { // An explicit dataSource was specified, so use it builder.addPropertyReference("dataSource", dataSource); parserContext.getRegistry().registerBeanDefinition(BeanIds.JDBC_USER_DETAILS_MANAGER, builder.getBeanDefinition()); - createDaoAuthenticationProviderIfRequired(createProvider, builder.getBeanDefinition(), parserContext); + createDaoAuthenticationProviderIfRequired(createProvider, jdbcUserServiceElt.getAttribute(ATT_HASH), builder.getBeanDefinition(), parserContext); } if (customUserServiceElt != null) { String id = customUserServiceElt.getAttribute(ATT_ID); BeanDefinition userDetailsService = parserContext.getRegistry().getBeanDefinition(id); - createDaoAuthenticationProviderIfRequired(createProvider, userDetailsService, parserContext); + createDaoAuthenticationProviderIfRequired(createProvider, customUserServiceElt.getAttribute(ATT_HASH), userDetailsService, parserContext); } return null; } - private void createDaoAuthenticationProviderIfRequired(boolean createProvider, BeanDefinition userDetailsService, ParserContext parserContext) { + private void createDaoAuthenticationProviderIfRequired(boolean createProvider, String hash, BeanDefinition userDetailsService, ParserContext parserContext) { if (createProvider) { + if (!StringUtils.hasText(hash)) { + hash = DEF_HASH_PLAINTEXT; + } RootBeanDefinition authProvider = new RootBeanDefinition(DaoAuthenticationProvider.class); authProvider.getPropertyValues().addPropertyValue("userDetailsService", userDetailsService); + + PasswordEncoder pwdEnc = null; + if (OPT_HASH_MD4_HEX.equals(hash)) { + pwdEnc = new Md4PasswordEncoder(); + ((Md4PasswordEncoder)pwdEnc).setEncodeHashAsBase64(false); + } else if (OPT_HASH_MD4_BASE64.equals(hash)) { + pwdEnc = new Md4PasswordEncoder(); + ((Md4PasswordEncoder)pwdEnc).setEncodeHashAsBase64(true); + } else if (OPT_HASH_MD5_HEX.equals(hash)) { + pwdEnc = new Md5PasswordEncoder(); + ((Md5PasswordEncoder)pwdEnc).setEncodeHashAsBase64(false); + } else if (OPT_HASH_MD5_BASE64.equals(hash)) { + pwdEnc = new Md5PasswordEncoder(); + ((Md5PasswordEncoder)pwdEnc).setEncodeHashAsBase64(true); + } else if (OPT_HASH_SHA_HEX.equals(hash)) { + pwdEnc = new ShaPasswordEncoder(); + ((ShaPasswordEncoder)pwdEnc).setEncodeHashAsBase64(false); + } else if (OPT_HASH_SHA_BASE64.equals(hash)) { + pwdEnc = new ShaPasswordEncoder(); + ((ShaPasswordEncoder)pwdEnc).setEncodeHashAsBase64(true); + } else { + pwdEnc = new PlaintextPasswordEncoder(); + } + authProvider.getPropertyValues().addPropertyValue("passwordEncoder", pwdEnc); + ConfigUtils.getRegisteredProviders(parserContext).add(authProvider); } } diff --git a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc index 6372407c3e..e57a361163 100644 --- a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc +++ b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.rnc @@ -10,6 +10,10 @@ start = http | ldap | repository # targetNamespace="http://www.springframework.org/schema/security" +hash = + ## Defines the type of hashing used on user passwords. If unspecified, "plaintext" is nominated, which indicates that the passwords are not hashed. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + attribute hash {"plaintext" | "sha:hex" | "sha:base64" | "md5:hex" | "md5:base64" | "md4:hex" | "md4:base64"} + pathType = ## Defines the type of pattern used to specify URL paths (either JDK 1.4-compatible regular expressions, or Apache Ant expressions). Defaults to "ant" if unspecified. attribute pathType {"ant" | "regex"} @@ -174,27 +178,38 @@ repository.attlist &= user-service = element user-service {user-service.attlist, (user*)} +user-service.attlist &= + hash? user-service.attlist &= attribute properties {xsd:string}* user = + ## Represents a user in the application. element user {user.attlist, empty} user.attlist &= + ## The username assigned to the user. attribute name {xsd:string} 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} 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:string} jdbc-user-service = ## Causes creation of a JDBC-based UserDetailsService. element jdbc-user-service {jdbc-user-service.attlist} +jdbc-user-service.attlist &= + hash? jdbc-user-service.attlist &= ## The bean ID of the DataSource which provides the required tables. attribute dataSource {xsd:string} custom-user-service = + ## Represents a UserDetailsService implementation that has been provided by you. Registration here will automate the creation of a DaoAuthenticationProvider that delegates to your UserDetailsService implementation. element custom-user-service {custom-user-service.attlist} +custom-user-service.attlist &= + hash? custom-user-service.attlist &= ## The bean ID of your custom UserDetailsService implementation. attribute id {xsd:string} diff --git a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd index 17715cedc8..f3ea903694 100644 --- a/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd +++ b/core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd @@ -1,6 +1,24 @@ + + + + Defines the type of hashing used on user passwords. If unspecified, "plaintext" is nominated, which indicates that the passwords are not hashed. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + + + + + + + + + + + + + + @@ -378,17 +396,48 @@ + + + Defines the type of hashing used on user passwords. If unspecified, "plaintext" is nominated, which indicates that the passwords are not hashed. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + + + + + + + + + + + + + + + Represents a user in the application. + - - - + + + 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). + + + + + One of more authorities granted to the user. Separate authorities with a comma (but no space). For example, "ROLE_USER,ROLE_ADMINISTRATOR" + + @@ -399,6 +448,22 @@ + + + Defines the type of hashing used on user passwords. If unspecified, "plaintext" is nominated, which indicates that the passwords are not hashed. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + + + + + + + + + + + + + The bean ID of the DataSource which provides the required tables. @@ -406,11 +471,30 @@ + + Represents a UserDetailsService implementation that has been provided by you. Registration here will automate the creation of a DaoAuthenticationProvider that delegates to your UserDetailsService implementation. + + + + Defines the type of hashing used on user passwords. If unspecified, "plaintext" is nominated, which indicates that the passwords are not hashed. We recommend strongly against using MD4, as it is a very weak hashing algorithm. + + + + + + + + + + + + + The bean ID of your custom UserDetailsService implementation. diff --git a/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml b/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml index e62775ca74..97527507c8 100644 --- a/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml +++ b/samples/tutorial/src/main/webapp/WEB-INF/applicationContext-security-ns.xml @@ -12,33 +12,30 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd"> - + - + - - - - - + + + + + - - \ No newline at end of file