Browse Source

SEC-1232: GlobalMethodSecurityBeanDefinitionParser support for mode='aspectj'

Also added this syntax to the aspectj sample.
Luke Taylor 15 years ago
parent
commit
a3ef8255d8

+ 27 - 7
config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java

@@ -37,6 +37,7 @@ import org.springframework.security.access.expression.method.ExpressionBasedPreI
 import org.springframework.security.access.intercept.AfterInvocationProviderManager;
 import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
 import org.springframework.security.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor;
+import org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor;
 import org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource;
 import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
 import org.springframework.security.access.prepost.PostInvocationAdviceProvider;
@@ -76,6 +77,7 @@ 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_MODE = "mode";
     private static final String ATT_ADVICE_ORDER = "order";
 
     public BeanDefinition parse(Element element, ParserContext pc) {
@@ -90,6 +92,8 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
         boolean jsr250Enabled = "enabled".equals(element.getAttribute(ATT_USE_JSR250));
         boolean useSecured = "enabled".equals(element.getAttribute(ATT_USE_SECURED));
         boolean prePostAnnotationsEnabled = "enabled".equals(element.getAttribute(ATT_USE_PREPOST));
+        boolean useAspectJ = "aspectj".equals(element.getAttribute(ATT_MODE));
+
         BeanDefinition preInvocationVoter = null;
         ManagedList<BeanMetadataElement> afterInvocationProviders = new ManagedList<BeanMetadataElement>();
 
@@ -165,6 +169,9 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
                 DomUtils.getChildElementsByTagName(element, PROTECT_POINTCUT));
 
         if (pointcutMap.size() > 0) {
+            if (useAspectJ) {
+                pc.getReaderContext().error("You can't use AspectJ mode with protect-pointcut definitions", source);
+            }
             // Only add it if there are actually any pointcuts defined.
             BeanDefinition mapBasedMetadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class);
             BeanReference ref = new RuntimeBeanReference(pc.getReaderContext().generateBeanName(mapBasedMetadataSource));
@@ -190,13 +197,22 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
         }
 
         String runAsManagerId = element.getAttribute(ATT_RUN_AS_MGR);
-
         BeanReference interceptor = registerMethodSecurityInterceptor(pc, accessManagerId, runAsManagerId,
-                metadataSource, afterInvocationProviders, source);
-
-        registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
+                metadataSource, afterInvocationProviders, source, useAspectJ);
+
+        if (useAspectJ) {
+            BeanDefinitionBuilder aspect =
+                BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.access.intercept.aspectj.aspect.AnnotationSecurityAspect");
+            aspect.setFactoryMethod("aspectOf");
+            aspect.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+            aspect.addPropertyValue("securityInterceptor", interceptor);
+            String id = pc.getReaderContext().registerWithGeneratedName(aspect.getBeanDefinition());
+            pc.registerBeanComponent(new BeanComponentDefinition(aspect.getBeanDefinition(), id));
+        } else {
+            registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER));
+            AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
+        }
 
-        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(pc, element);
         pc.popAndRegisterContainingComponent();
 
         return null;
@@ -284,12 +300,16 @@ public class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionP
     }
 
     private BeanReference registerMethodSecurityInterceptor(ParserContext pc, String accessManagerId,
-            String runAsManagerId, BeanReference metadataSource, List<BeanMetadataElement> afterInvocationProviders, Object source) {
-        BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class);
+            String runAsManagerId, BeanReference metadataSource,
+            List<BeanMetadataElement> afterInvocationProviders, Object source, boolean useAspectJ) {
+        BeanDefinitionBuilder bldr =
+            BeanDefinitionBuilder.rootBeanDefinition(useAspectJ ?
+                    AspectJMethodSecurityInterceptor.class : MethodSecurityInterceptor.class);
         bldr.getRawBeanDefinition().setSource(source);
         bldr.addPropertyReference("accessDecisionManager", accessManagerId);
         bldr.addPropertyValue("authenticationManager", new RootBeanDefinition(AuthenticationManagerDelegator.class));
         bldr.addPropertyValue("securityMetadataSource", metadataSource);
+
         if (StringUtils.hasText(runAsManagerId)) {
             bldr.addPropertyReference("runAsManager", runAsManagerId);
         }

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

@@ -216,6 +216,9 @@ global-method-security.attlist &=
     attribute order {xsd:token}?
 global-method-security.attlist &=
     attribute proxy-target-class {boolean}?
+global-method-security.attlist &=
+    ## Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.
+    attribute mode {"aspectj"}?
 
 after-invocation-provider =
     ## Allows addition of extra AfterInvocationProvider beans which should be called by the MethodSecurityInterceptor created by global-method-security.

+ 10 - 0
config/src/main/resources/org/springframework/security/config/spring-security-3.1.xsd

@@ -574,6 +574,16 @@
       </xs:annotation>
     </xs:attribute>
     <xs:attribute name="proxy-target-class" type="security:boolean"/>
+    <xs:attribute name="mode">
+      <xs:annotation>
+        <xs:documentation>Can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.</xs:documentation>
+      </xs:annotation>
+      <xs:simpleType>
+        <xs:restriction base="xs:token">
+          <xs:enumeration value="aspectj"/>
+        </xs:restriction>
+      </xs:simpleType>
+    </xs:attribute>
   </xs:attributeGroup>
   
   

+ 9 - 0
samples/aspectj/aspectj.gradle

@@ -0,0 +1,9 @@
+
+dependencies {
+    compile project(':spring-security-core')
+
+    aspectpath project(':spring-security-aspects')
+
+    runtime project(':spring-security-config'),
+            project(':spring-security-aspects')
+}

+ 6 - 2
samples/aspectj/src/main/resources/aspectj-context.xml

@@ -1,8 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+    xmlns:sec="http://www.springframework.org/schema/security"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
 
+    <sec:global-method-security secured-annotations="enabled" mode="aspectj" />
+<!--
     <bean id="aspectJSecurityInterceptor"
         class="org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor">
         <property name="authenticationManager" ref="authenticationManager" />
@@ -36,7 +40,7 @@
         factory-method="aspectOf">
         <property name="securityInterceptor" ref="aspectJSecurityInterceptor" />
     </bean>
-
+ -->
     <bean class="sample.aspectj.Service" />
 
     <bean class="sample.aspectj.SecuredService" />

+ 2 - 1
settings.gradle

@@ -13,7 +13,8 @@ def String[] modules = [
 def String[] samples = [
     'tutorial',
     'contacts',
-    'openid'
+    'openid',
+    'aspectj'
 ]
 
 def String[] docs = [