From 1cfd886517226a900d5c4d10913a03a810fc741d Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Mon, 18 Aug 2008 23:31:14 +0000 Subject: [PATCH] SEC-922: Spring Security should respect Spring XML boolean operators for AJ pointcut http://jira.springframework.org/browse/SEC-922. Added method to substitute boolean operators "and, not, or" with aspectj versions "&&, !, ||". --- ...thodSecurityBeanDefinitionParserTests.java | 46 ++++++++++++++++--- .../method/ProtectPointcutPostProcessor.java | 14 +++++- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/core-tiger/src/test/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParserTests.java b/core-tiger/src/test/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParserTests.java index 3b88528df9..4b2c63767e 100644 --- a/core-tiger/src/test/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParserTests.java +++ b/core-tiger/src/test/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParserTests.java @@ -1,6 +1,6 @@ package org.springframework.security.config; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static org.springframework.security.config.ConfigTestUtils.*; import org.junit.After; @@ -42,8 +42,10 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { public void closeAppContext() { if (appContext != null) { appContext.close(); + appContext = null; } SecurityContextHolder.clearContext(); + target = null; } @Test(expected=AuthenticationCredentialsNotFoundException.class) @@ -55,8 +57,7 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { @Test public void targetShouldAllowProtectedMethodInvocationWithCorrectRole() { loadContext(); - UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password", - new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_USER")}); + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password"); SecurityContextHolder.getContext().setAuthentication(token); target.someUserMethod1(); @@ -111,13 +112,46 @@ public class GlobalMethodSecurityBeanDefinitionParserTests { setContext( "" + "" + - " " + - " " + + " " + + " " + "" + ConfigTestUtils.AUTH_PROVIDER_XML ); SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password")); target = (BusinessService) appContext.getBean("target"); - // someOther(int) should not be matched by someOther(String) + // someOther(int) should not be matched by someOther(String), but should require ROLE_USER + target.someOther(0); + + try { + // String version should required admin role + target.someOther("somestring"); + fail("Expected AccessDeniedException"); + } catch (AccessDeniedException expected) { + } + } + + @Test + public void supportsBooleanPointcutExpressions() { + setContext( + "" + + "" + + " " + + "" + ConfigTestUtils.AUTH_PROVIDER_XML + ); + target = (BusinessService) appContext.getBean("target"); + // String method should not be protected + target.someOther("somestring"); + + // All others should require ROLE_USER + try { + target.someOther(0); + fail("Expected AuthenticationCredentialsNotFoundException"); + } catch (AuthenticationCredentialsNotFoundException expected) { + } + + SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("user", "password")); target.someOther(0); } diff --git a/core/src/main/java/org/springframework/security/intercept/method/ProtectPointcutPostProcessor.java b/core/src/main/java/org/springframework/security/intercept/method/ProtectPointcutPostProcessor.java index 809090018b..92a9b9cc1f 100644 --- a/core/src/main/java/org/springframework/security/intercept/method/ProtectPointcutPostProcessor.java +++ b/core/src/main/java/org/springframework/security/intercept/method/ProtectPointcutPostProcessor.java @@ -17,6 +17,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.intercept.method.aopalliance.MethodDefinitionSourceAdvisor; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Parses AspectJ pointcut expressions, registering methods that match the pointcut with a @@ -141,9 +142,10 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor { } } - public void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) { + private void addPointcut(String pointcutExpression, ConfigAttributeDefinition definition) { Assert.hasText(pointcutExpression, "An AspectJ pointcut expression is required"); Assert.notNull(definition, "ConfigAttributeDefinition required"); + pointcutExpression = replaceBooleanOperators(pointcutExpression); pointcutMap.put(pointcutExpression, definition); if (logger.isDebugEnabled()) { @@ -151,4 +153,14 @@ public final class ProtectPointcutPostProcessor implements BeanPostProcessor { } } + /** + * @see org.springframework.aop.aspectj.AspectJExpressionPointcut#replaceBooleanOperators + */ + private String replaceBooleanOperators(String pcExpr) { + pcExpr = StringUtils.replace(pcExpr," and "," && "); + pcExpr = StringUtils.replace(pcExpr, " or ", " || "); + pcExpr = StringUtils.replace(pcExpr, " not ", " ! "); + return pcExpr; + } + }