diff --git a/config/config.gradle b/config/config.gradle index cf73a8f1e7..87661e85a1 100644 --- a/config/config.gradle +++ b/config/config.gradle @@ -5,6 +5,7 @@ compileTestJava.dependsOn(':spring-security-core:compileTestJava') dependencies { compile project(':spring-security-core'), project(':spring-security-web'), + 'aopalliance:aopalliance:1.0', "org.aspectj:aspectjweaver:$aspectjVersion", "org.springframework:spring-aop:$springVersion", "org.springframework:spring-context:$springVersion", @@ -18,11 +19,6 @@ dependencies { project(':spring-security-openid'), files(this.project(':spring-security-core').sourceSets.test.classesDir), 'javax.annotation:jsr250-api:1.0', - 'aopalliance:aopalliance:1.0', "org.springframework.ldap:spring-ldap-core:$springLdapVersion", "org.springframework:spring-jdbc:$springVersion" } - -task show << { - println dependencies -} \ No newline at end of file diff --git a/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java index 7c04988414..b2f614c2ec 100644 --- a/config/src/main/java/org/springframework/security/config/method/GlobalMethodSecurityBeanDefinitionParser.java +++ b/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 afterInvocationProviders = new ManagedList(); @@ -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); + metadataSource, afterInvocationProviders, source, useAspectJ); - registerAdvisor(pc, interceptor, metadataSource, source, element.getAttribute(ATT_ADVICE_ORDER)); + 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 afterInvocationProviders, Object source) { - BeanDefinitionBuilder bldr = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class); + String runAsManagerId, BeanReference metadataSource, + List 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); } diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.rnc index 3884ece54b..6b6fa83557 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.rnc @@ -208,6 +208,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. diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.xsd index bcb1082181..5e06259693 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.3.xsd @@ -539,6 +539,16 @@ + + + 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. + + + + + + + diff --git a/samples/aspectj/aspectj.gradle b/samples/aspectj/aspectj.gradle new file mode 100644 index 0000000000..de56c504b5 --- /dev/null +++ b/samples/aspectj/aspectj.gradle @@ -0,0 +1,8 @@ +dependencies { + compile project(':spring-security-core') + + aspectpath project(':spring-security-aspects') + + runtime project(':spring-security-config'), + project(':spring-security-aspects') +} \ No newline at end of file diff --git a/samples/aspectj/src/main/resources/aspectj-context.xml b/samples/aspectj/src/main/resources/aspectj-context.xml index ef48497453..4df00d5ceb 100644 --- a/samples/aspectj/src/main/resources/aspectj-context.xml +++ b/samples/aspectj/src/main/resources/aspectj-context.xml @@ -1,41 +1,11 @@ + 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.0.3.xsd"> - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/settings.gradle b/settings.gradle index cb36923da0..4151bf051a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,7 +13,8 @@ def String[] modules = [ def String[] samples = [ 'tutorial', 'contacts', - 'openid' + 'openid', + 'aspectj' ] def String[] docs = [