2
0
Эх сурвалжийг харах

SEC-1213: Added "order" atrribute to global-method-security

Luke Taylor 16 жил өмнө
parent
commit
8632946f30

+ 18 - 8
config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java

@@ -75,8 +75,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
     private static final String ATT_USE_SECURED = "secured-annotations";
     private static final String ATT_USE_PREPOST = "pre-post-annotations";
     private static final String ATT_REF = "ref";
+    private static final String ATT_ADVICE_ORDER = "order";
 
-    @SuppressWarnings("unchecked")
+ //   @SuppressWarnings("unchecked")
     public BeanDefinition parse(Element element, ParserContext pc) {
         CompositeComponentDefinition compositeDef =
             new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
@@ -84,7 +85,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
 
         Object source = pc.extractSource(element);
         // The list of method metadata delegates
-        ManagedList delegates = new ManagedList();
+        ManagedList<BeanMetadataElement> delegates = new ManagedList<BeanMetadataElement>();
 
         boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
         boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
@@ -165,9 +166,12 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
 
         if (pointcutMap.size() > 0) {
             // Only add it if there are actually any pointcuts defined.
-            MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource = new MapBasedMethodSecurityMetadataSource();
-            delegates.add(mapBasedMethodSecurityMetadataSource);
-            registerProtectPointcutPostProcessor(pc, pointcutMap, mapBasedMethodSecurityMetadataSource, source);
+            BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
+            BeanReference ref = new RuntimeBeanReference(pc.getReaderContext().registerWithGeneratedName(mapBasedMetadataSource));
+
+            delegates.add(ref);
+            pc.registerBeanComponent(new BeanComponentDefinition(mapBasedMetadataSource, ref.getBeanName()));
+            registerProtectPointcutPostProcessor(pc, pointcutMap, ref, source);
         }
 
         BeanReference metadataSource = registerDelegatingMethodSecurityMetadataSource(pc, delegates, source);
@@ -190,10 +194,11 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
         BeanReference interceptor = registerMethodSecurityInterceptor(pc, accessManagerId, runAsManagerId,
                 metadataSource, afterInvocationProviders, source);
 
-        registerAdvisor(pc, interceptor, metadataSource, source);
+        registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
 
         AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
         pc.popAndRegisterContainingComponent();
+
         return null;
     }
 
@@ -241,7 +246,7 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
 
     private void registerProtectPointcutPostProcessor(ParserContext parserContext,
             Map<String, List<ConfigAttribute>> pointcutMap,
-            MapBasedMethodSecurityMetadataSource mapBasedMethodSecurityMetadataSource, Object source) {
+            BeanReference mapBasedMethodSecurityMetadataSource, Object source) {
         RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class);
         ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         ppbp.setSource(source);
@@ -304,11 +309,16 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
         return new RuntimeBeanReference(id);
     }
 
-    private void registerAdvisor(ParserContext parserContext, BeanReference interceptor, BeanReference metadataSource, Object source) {
+    private void registerAdvisor(ParserContext parserContext, BeanReference interceptor, BeanReference metadataSource, Object source, String adviceOrder) {
         if (parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_SECURITY_METADATA_SOURCE_ADVISOR)) {
             parserContext.getReaderContext().error("Duplicate <global-method-security> detected.", source);
         }
         RootBeanDefinition advisor = new RootBeanDefinition(MethodSecurityMetadataSourceAdvisor.class);
+
+        if (StringUtils.hasText(adviceOrder)) {
+            advisor.getPropertyValues().addPropertyValue("order", adviceOrder);
+        }
+
         // advisor must be an infrastructure bean as Spring's InfrastructureAdvisorAutoProxyCreator will ignore it
         // otherwise
         advisor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

+ 3 - 0
config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc

@@ -203,6 +203,9 @@ global-method-security.attlist &=
 global-method-security.attlist &=
     ## Optional RunAsmanager implementation which will be used by the configured MethodSecurityInterceptor
     attribute run-as-manager-ref {xsd:token}?
+global-method-security.attlist &=
+    ## Allows the advice "order" to be set for the method security interceptor.
+    attribute order {xsd:token}?
     
 after-invocation-provider =
     ## Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.

+ 6 - 0
config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd

@@ -672,6 +672,12 @@
                configured MethodSecurityInterceptor</xs:documentation>
          </xs:annotation>
       </xs:attribute>
+      <xs:attribute name="order" type="xs:token">
+         <xs:annotation>
+            <xs:documentation>Allows the advice "order" to be set for the method security
+               interceptor.</xs:documentation>
+         </xs:annotation>
+      </xs:attribute>
    </xs:attributeGroup>
    <xs:element name="custom-after-invocation-provider">
       <xs:annotation>

+ 9 - 1
config/src/test/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParserTests.java

@@ -8,6 +8,8 @@ import java.util.List;
 
 import org.junit.After;
 import org.junit.Test;
+import org.springframework.aop.Advisor;
+import org.springframework.aop.framework.Advised;
 import org.springframework.beans.MutablePropertyValues;
 import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
 import org.springframework.context.ApplicationContext;
@@ -46,7 +48,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
     public void loadContext() {
         setContext(
                 "<b:bean id='target' class='org.springframework.security.access.annotation.BusinessServiceImpl'/>" +
-                "<global-method-security>" +
+                "<global-method-security order='1001'>" +
                 "    <protect-pointcut expression='execution(* *.someUser*(..))' access='ROLE_USER'/>" +
                 "    <protect-pointcut expression='execution(* *.someAdmin*(..))' access='ROLE_ADMIN'/>" +
                 "</global-method-security>" + ConfigTestUtils.AUTH_PROVIDER_XML
@@ -67,6 +69,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
     @Test(expected=AuthenticationCredentialsNotFoundException.class)
     public void targetShouldPreventProtectedMethodInvocationWithNoContext() {
         loadContext();
+
         target.someUserMethod1();
     }
 
@@ -77,6 +80,11 @@ public class GlobalMethodSecurityBeanDefinitionParserTests {
         SecurityContextHolder.getContext().setAuthentication(token);
 
         target.someUserMethod1();
+
+        // SEC-1213. Check the order
+        Advisor[] advisors = ((Advised)target).getAdvisors();
+        assertEquals(1, advisors.length);
+        assertEquals(1001, ((MethodSecurityMetadataSourceAdvisor)advisors[0]).getOrder());
     }
 
     @Test(expected=AccessDeniedException.class)