|
@@ -15,6 +15,9 @@
|
|
|
|
|
|
package org.springframework.security.access.intercept.aopalliance;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.ObjectInputStream;
|
|
|
+import java.io.Serializable;
|
|
|
import java.lang.reflect.AccessibleObject;
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
@@ -31,7 +34,7 @@ import org.springframework.util.Assert;
|
|
|
|
|
|
/**
|
|
|
* Advisor driven by a {@link MethodSecurityMetadataSource}, used to exclude a {@link MethodSecurityInterceptor} from
|
|
|
- * public (ie non-secure) methods.
|
|
|
+ * public (non-secure) methods.
|
|
|
* <p>
|
|
|
* Because the AOP framework caches advice calculations, this is normally faster than just letting the
|
|
|
* <code>MethodSecurityInterceptor</code> run and find out itself that it has no work to do.
|
|
@@ -44,23 +47,25 @@ import org.springframework.util.Assert;
|
|
|
* Based on Spring's TransactionAttributeSourceAdvisor.
|
|
|
*
|
|
|
* @author Ben Alex
|
|
|
+ * @author Luke Taylor
|
|
|
*/
|
|
|
public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
|
|
|
//~ Instance fields ================================================================================================
|
|
|
|
|
|
- private MethodSecurityMetadataSource attributeSource;
|
|
|
- private MethodSecurityInterceptor interceptor;
|
|
|
- private Pointcut pointcut = new MethodSecurityMetadataSourcePointcut();
|
|
|
+ private transient MethodSecurityMetadataSource attributeSource;
|
|
|
+ private transient MethodSecurityInterceptor interceptor;
|
|
|
+ private final Pointcut pointcut = new MethodSecurityMetadataSourcePointcut();
|
|
|
private BeanFactory beanFactory;
|
|
|
private String adviceBeanName;
|
|
|
- private final Object adviceMonitor = new Object();
|
|
|
+ private String metadataSourceBeanName;
|
|
|
+ private final Serializable adviceMonitor = new Serializable() {};
|
|
|
|
|
|
//~ Constructors ===================================================================================================
|
|
|
|
|
|
/**
|
|
|
* @deprecated use the decoupled approach instead
|
|
|
*/
|
|
|
- public MethodSecurityMetadataSourceAdvisor(MethodSecurityInterceptor advice) {
|
|
|
+ MethodSecurityMetadataSourceAdvisor(MethodSecurityInterceptor advice) {
|
|
|
Assert.notNull(advice.getSecurityMetadataSource(), "Cannot construct a MethodSecurityMetadataSourceAdvisor using a " +
|
|
|
"MethodSecurityInterceptor that has no SecurityMetadataSource configured");
|
|
|
|
|
@@ -71,21 +76,22 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor
|
|
|
/**
|
|
|
* Alternative constructor for situations where we want the advisor decoupled from the advice. Instead the advice
|
|
|
* bean name should be set. This prevents eager instantiation of the interceptor
|
|
|
- * (and hence the AuthenticationManager). See SEC-773, for example.
|
|
|
- * <p>
|
|
|
- * This is essentially the approach taken by subclasses of Spring's {@code AbstractBeanFactoryPointcutAdvisor},
|
|
|
- * which this class should extend in future. The original hierarchy and constructor have been retained for backwards
|
|
|
- * compatibility.
|
|
|
+ * (and hence the AuthenticationManager). See SEC-773, for example. The metadataSourceBeanName is used rather than
|
|
|
+ * a direct reference to support serialization via a bean factory lookup.
|
|
|
*
|
|
|
* @param adviceBeanName name of the MethodSecurityInterceptor bean
|
|
|
- * @param attributeSource the attribute source (should be the same as the one used on the interceptor)
|
|
|
+ * @param attributeSource the SecurityMetadataSource (should be the same as the one used on the interceptor)
|
|
|
+ * @param attributeSourceBeanName the bean name of the attributeSource (required for serialization)
|
|
|
*/
|
|
|
- public MethodSecurityMetadataSourceAdvisor(String adviceBeanName, MethodSecurityMetadataSource attributeSource) {
|
|
|
+ public MethodSecurityMetadataSourceAdvisor(String adviceBeanName, MethodSecurityMetadataSource attributeSource,
|
|
|
+ String attributeSourceBeanName) {
|
|
|
Assert.notNull(adviceBeanName, "The adviceBeanName cannot be null");
|
|
|
Assert.notNull(attributeSource, "The attributeSource cannot be null");
|
|
|
+ Assert.notNull(attributeSourceBeanName, "The attributeSourceBeanName cannot be null");
|
|
|
|
|
|
this.adviceBeanName = adviceBeanName;
|
|
|
this.attributeSource = attributeSource;
|
|
|
+ this.metadataSourceBeanName = attributeSourceBeanName;
|
|
|
}
|
|
|
|
|
|
//~ Methods ========================================================================================================
|
|
@@ -99,8 +105,7 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor
|
|
|
if (interceptor == null) {
|
|
|
Assert.notNull(adviceBeanName, "'adviceBeanName' must be set for use with bean factory lookup.");
|
|
|
Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
|
|
- interceptor = (MethodSecurityInterceptor)
|
|
|
- beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class);
|
|
|
+ interceptor = beanFactory.getBean(this.adviceBeanName, MethodSecurityInterceptor.class);
|
|
|
}
|
|
|
return interceptor;
|
|
|
}
|
|
@@ -110,9 +115,15 @@ public class MethodSecurityMetadataSourceAdvisor extends AbstractPointcutAdvisor
|
|
|
this.beanFactory = beanFactory;
|
|
|
}
|
|
|
|
|
|
+ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
|
|
+ ois.defaultReadObject();
|
|
|
+
|
|
|
+ attributeSource = beanFactory.getBean(metadataSourceBeanName, MethodSecurityMetadataSource.class);
|
|
|
+ }
|
|
|
+
|
|
|
//~ Inner Classes ==================================================================================================
|
|
|
|
|
|
- class MethodSecurityMetadataSourcePointcut extends StaticMethodMatcherPointcut {
|
|
|
+ class MethodSecurityMetadataSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
|
|
|
@SuppressWarnings("unchecked")
|
|
|
public boolean matches(Method m, Class targetClass) {
|
|
|
return attributeSource.getAttributes(m, targetClass) != null;
|