فهرست منبع

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.

Luke Taylor 17 سال پیش
والد
کامیت
aba5a22b6c

+ 9 - 6
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);

+ 7 - 0
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

+ 14 - 0
core/src/main/resources/org/springframework/security/config/spring-security-2.0.xsd

@@ -150,6 +150,14 @@
       <xs:enumeration value="false"/>
     </xs:restriction>
   </xs:simpleType>
+  <xs:attributeGroup name="role-prefix">
+    <xs:attribute name="role-prefix" use="required" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
+          persistent storage (e.g. "ROLE_").</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
+  </xs:attributeGroup>
   <xs:element name="ldap-server">
     <xs:annotation>
       <xs:documentation>Defines an LDAP server location or starts an embedded server. The url
@@ -1168,6 +1176,12 @@
         username.</xs:documentation>
       </xs:annotation>
     </xs:attribute>
+    <xs:attribute name="role-prefix" type="xs:string">
+      <xs:annotation>
+        <xs:documentation>A non-empty string prefix that will be added to role strings loaded from
+          persistent storage (e.g. "ROLE_").</xs:documentation>
+      </xs:annotation>
+    </xs:attribute>
   </xs:attributeGroup>
   <xs:element name="any-user-service" abstract="true"/>
   <xs:group name="custom-filter">

+ 12 - 1
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("<jdbc-user-service id='myUserService' cache-ref='userCache' data-source-ref='dataSource'/>" 
@@ -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("<jdbc-user-service id='myUserService' role-prefix='PREFIX_' data-source-ref='dataSource'/>" + 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);