فهرست منبع

SEC-1768: Added tests to reproduce "double-proxying" issue combining intercept-methods and tx-annotation-driven. Problem is caused by use of ProxyFactoryBean with auto-proxying.

Luke Taylor 14 سال پیش
والد
کامیت
5a1ddc660b

+ 2 - 5
config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java

@@ -1,9 +1,5 @@
 package org.springframework.security.config.method;
 package org.springframework.security.config.method;
 
 
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
 import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
 import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.BeanDefinitionHolder;
 import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -13,7 +9,6 @@ import org.springframework.beans.factory.support.ManagedMap;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.support.RootBeanDefinition;
 import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
 import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
 import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.security.access.ConfigAttribute;
 import org.springframework.security.access.SecurityConfig;
 import org.springframework.security.access.SecurityConfig;
 import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
 import org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor;
 import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
 import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
@@ -24,6 +19,8 @@ import org.springframework.util.xml.DomUtils;
 import org.w3c.dom.Element;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.Node;
 
 
+import java.util.*;
+
 /**
 /**
  * @author Luke Taylor
  * @author Luke Taylor
  * @author Ben Alex
  * @author Ben Alex

+ 23 - 0
config/src/test/java/org/springframework/security/config/MockTransactionManager.java

@@ -0,0 +1,23 @@
+package org.springframework.security.config;
+
+import static org.mockito.Mockito.mock;
+
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+
+/**
+ * @author Luke Taylor
+ */
+public class MockTransactionManager implements PlatformTransactionManager {
+    public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
+        return mock(TransactionStatus.class);
+    }
+
+    public void commit(TransactionStatus status) throws TransactionException {
+    }
+
+    public void rollback(TransactionStatus status) throws TransactionException {
+    }
+}

+ 1 - 0
config/src/test/java/org/springframework/security/config/TestBusinessBeanImpl.java

@@ -2,6 +2,7 @@ package org.springframework.security.config;
 
 
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.ApplicationListener;
 import org.springframework.security.core.session.SessionCreationEvent;
 import org.springframework.security.core.session.SessionCreationEvent;
+import org.springframework.transaction.annotation.Transactional;
 
 
 /**
 /**
  * @author Luke Taylor
  * @author Luke Taylor

+ 25 - 0
config/src/test/java/org/springframework/security/config/TransactionalTestBusinessBean.java

@@ -0,0 +1,25 @@
+package org.springframework.security.config;
+
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Luke Taylor
+ */
+public class TransactionalTestBusinessBean implements TestBusinessBean {
+    public void setInteger(int i) {
+    }
+
+    public int getInteger() {
+        return 0;
+    }
+
+    public void setString(String s) {
+    }
+
+    @Transactional
+    public void doSomething() {
+    }
+
+    public void unprotected() {
+    }
+}

+ 33 - 14
config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java

@@ -2,9 +2,14 @@ package org.springframework.security.config.method;
 
 
 import static org.junit.Assert.*;
 import static org.junit.Assert.*;
 
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.*;
+import org.junit.runner.RunWith;
+import org.springframework.aop.framework.Advised;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.access.AccessDeniedException;
@@ -13,29 +18,34 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
 import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
 import org.springframework.security.config.TestBusinessBean;
 import org.springframework.security.config.TestBusinessBean;
+import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.authority.AuthorityUtils;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 
 /**
 /**
  * @author Luke Taylor
  * @author Luke Taylor
  */
  */
-public class InterceptMethodsBeanDefinitionDecoratorTests {
-    private ClassPathXmlApplicationContext appContext;
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = "classpath:org/springframework/security/config/method-security.xml")
+public class InterceptMethodsBeanDefinitionDecoratorTests implements ApplicationContextAware {
+    @Autowired
+    @Qualifier("target")
     private TestBusinessBean target;
     private TestBusinessBean target;
+    @Autowired
+    @Qualifier("transactionalTarget")
+    private TestBusinessBean transactionalTarget;
+    private ApplicationContext appContext;
 
 
-    @Before
-    public void loadContext() {
+    @BeforeClass
+    public static void loadContext() {
         // Set value for placeholder
         // Set value for placeholder
         System.setProperty("admin.role", "ROLE_ADMIN");
         System.setProperty("admin.role", "ROLE_ADMIN");
-        appContext = new ClassPathXmlApplicationContext("org/springframework/security/config/method-security.xml");
-        target = (TestBusinessBean) appContext.getBean("target");
     }
     }
 
 
     @After
     @After
-    public void closeAppContext() {
-        if (appContext != null) {
-            appContext.close();
-        }
+    public void clearContext() {
         SecurityContextHolder.clearContext();
         SecurityContextHolder.clearContext();
     }
     }
 
 
@@ -74,6 +84,15 @@ public class InterceptMethodsBeanDefinitionDecoratorTests {
         SecurityContextHolder.getContext().setAuthentication(token);
         SecurityContextHolder.getContext().setAuthentication(token);
 
 
         target.doSomething();
         target.doSomething();
-        fail("Expected AccessDeniedException");
+    }
+
+    @Test(expected = AuthenticationException.class)
+    public void transactionalMethodsShouldBeSecured() throws Exception {
+        transactionalTarget.doSomething();
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.appContext = applicationContext;
     }
     }
 }
 }

+ 14 - 1
config/src/test/resources/org/springframework/security/config/method-security.xml

@@ -3,11 +3,24 @@
 <b:beans xmlns="http://www.springframework.org/schema/security"
 <b:beans xmlns="http://www.springframework.org/schema/security"
     xmlns:b="http://www.springframework.org/schema/beans"
     xmlns:b="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     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.xsd">
+        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
+        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
+
+    <tx:annotation-driven />
+
+    <b:bean name="transactionManager" class="org.springframework.security.config.MockTransactionManager" />
 
 
     <b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>
     <b:bean class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'/>
 
 
+    <b:bean id="transactionalTarget" class="org.springframework.security.config.TransactionalTestBusinessBean">
+        <intercept-methods>
+            <protect method="*" access="ROLE_USER" />
+        </intercept-methods>
+    </b:bean>
+
+
     <b:bean id="target" class="org.springframework.security.config.TestBusinessBeanImpl">
     <b:bean id="target" class="org.springframework.security.config.TestBusinessBeanImpl">
         <!-- This will add a security interceptor to the bean -->
         <!-- This will add a security interceptor to the bean -->
         <intercept-methods>
         <intercept-methods>