From aba5a22b6c80dd4fc51ade9d3a3590a3b4b9d3b9 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Mon, 21 Apr 2008 17:44:32 +0000 Subject: [PATCH] SEC-789: Add support for optional role-prefix attribute to namespace http://jira.springframework.org/browse/SEC-789. Added support for role-prefix to jdbc-user-service element. --- .../JdbcUserServiceBeanDefinitionParser.java | 15 +++++++++------ .../security/config/spring-security-2.0.rnc | 7 +++++++ .../security/config/spring-security-2.0.xsd | 14 ++++++++++++++ .../JdbcUserServiceBeanDefinitionParserTests.java | 13 ++++++++++++- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParser.java index e4458b0d32..e4628b6c05 100644 --- a/core/src/main/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParser.java @@ -4,7 +4,6 @@ import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager; import org.springframework.util.StringUtils; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.beans.factory.BeanDefinitionStoreException; import org.w3c.dom.Element; @@ -17,26 +16,30 @@ public class JdbcUserServiceBeanDefinitionParser extends AbstractUserDetailsServ static final String ATT_USERS_BY_USERNAME_QUERY = "users-by-username-query"; static final String ATT_AUTHORITIES_BY_USERNAME_QUERY = "authorities-by-username-query"; static final String ATT_GROUP_AUTHORITIES_QUERY = "group-authorities-by-username-query"; + static final String ATT_ROLE_PREFIX = "role-prefix"; protected Class getBeanClass(Element element) { return JdbcUserDetailsManager.class; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - // TODO: Set authenticationManager property String dataSource = element.getAttribute(ATT_DATA_SOURCE); - // An explicit dataSource was specified, so use it + if (dataSource != null) { builder.addPropertyReference("dataSource", dataSource); } else { - // TODO: Have some sensible fallback if dataSource not specified, eg autowire - throw new BeanDefinitionStoreException(ATT_DATA_SOURCE + " is required for " - + Elements.JDBC_USER_SERVICE ); + parserContext.getReaderContext().error(ATT_DATA_SOURCE + " is required for " + + Elements.JDBC_USER_SERVICE, parserContext.extractSource(element)); } String usersQuery = element.getAttribute(ATT_USERS_BY_USERNAME_QUERY); String authoritiesQuery = element.getAttribute(ATT_AUTHORITIES_BY_USERNAME_QUERY); String groupAuthoritiesQuery = element.getAttribute(ATT_GROUP_AUTHORITIES_QUERY); + String rolePrefix = element.getAttribute(ATT_ROLE_PREFIX); + + if (StringUtils.hasText(rolePrefix)) { + builder.addPropertyValue("rolePrefix", rolePrefix); + } if (StringUtils.hasText(usersQuery)) { builder.addPropertyValue("usersByUsernameQuery", usersQuery); 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 8c46dd6f72..005814ec01 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 @@ -52,6 +52,10 @@ system-wide = boolean = "true" | "false" +role-prefix = + ## A non-empty string prefix that will be added to role strings loaded from persistent storage (e.g. "ROLE_"). + attribute role-prefix {xsd:string} + ldap-server = ## Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied. @@ -110,6 +114,7 @@ ldap-us.attlist &= ldap-us.attlist &= cache-ref? + ldap-authentication-provider = ## Sets up an ldap authentication provider element ldap-authentication-provider {ldap-ap.attlist, password-compare-element?} @@ -426,6 +431,8 @@ jdbc-user-service.attlist &= jdbc-user-service.attlist &= ## An SQL statement to query user's group authorities given a username. attribute group-authorities-by-username-query {xsd:string}? +jdbc-user-service.attlist &= + role-prefix? any-user-service = user-service | jdbc-user-service | ldap-user-service 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 f1dd38fa30..cebce890ac 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 @@ -150,6 +150,14 @@ + + + + A non-empty string prefix that will be added to role strings loaded from + persistent storage (e.g. "ROLE_"). + + + Defines an LDAP server location or starts an embedded server. The url @@ -1168,6 +1176,12 @@ username. + + + A non-empty string prefix that will be added to role strings loaded from + persistent storage (e.g. "ROLE_"). + + diff --git a/core/src/test/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParserTests.java b/core/src/test/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParserTests.java index 789435ed75..57b1f2d79d 100644 --- a/core/src/test/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParserTests.java +++ b/core/src/test/java/org/springframework/security/config/JdbcUserServiceBeanDefinitionParserTests.java @@ -10,7 +10,9 @@ import org.springframework.security.AuthenticationManager; import org.springframework.security.providers.ProviderManager; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.providers.dao.DaoAuthenticationProvider; +import org.springframework.security.userdetails.UserDetails; import org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager; +import org.springframework.security.util.AuthorityUtils; import org.springframework.security.util.InMemoryXmlApplicationContext; /** @@ -61,7 +63,7 @@ public class JdbcUserServiceBeanDefinitionParserTests { JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService"); assertTrue(mgr.loadUserByUsername("rod") != null); } - + @Test public void cacheRefIsparsedCorrectly() { setContext("" @@ -94,6 +96,15 @@ public class JdbcUserServiceBeanDefinitionParserTests { provider.authenticate(new UsernamePasswordAuthenticationToken("rod","koala")); assertNotNull("Cache should contain user after authentication", provider.getUserCache().getUserFromCache("rod")); } + + @Test + public void rolePrefixIsUsedWhenSet() { + setContext("" + DATA_SOURCE); + JdbcUserDetailsManager mgr = (JdbcUserDetailsManager) appContext.getBean("myUserService"); + UserDetails rod = mgr.loadUserByUsername("rod"); + assertTrue(AuthorityUtils.authorityArrayToSet(rod.getAuthorities()).contains("PREFIX_ROLE_SUPERVISOR")); + } + private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context);