Secure Object ImplementationsAOP Alliance (MethodInvocation) Security Interceptor Prior to Spring Security 2.0, securing MethodInvocations
needed quite a lot of boiler plate configuration. Now the recommended approach for
method security is to use namespace
configuration. This way the method security infrastructure beans are configured
automatically for you so you don't really need to know about the implementation classes.
We'll just provide a quick overview of the classes that are involved here. Method security in enforced using a MethodSecurityInterceptor,
which secures MethodInvocations. Depending on the configuration
approach, an interceptor may be specific to a single bean or shared between multiple
beans. The interceptor uses a
MethodSecurityMetadataSource instance to obtain the
configuration attributes that apply to a particular method invocation.
MapBasedMethodSecurityMetadataSource is used to store
configuration attributes keyed by method names (which can be wildcarded) and will be
used internally when the attributes are defined in the application context using the
<intercept-methods> or <protect-point>
elements. Other implementations will be used to handle annotation-based configuration. Explicit MethodSecurityInterceptor Configuration You can of course configure a MethodSecurityIterceptor
directly in your application context for use with one of Spring AOP's proxying
mechanisms:
]]>
AspectJ (JoinPoint) Security InterceptorThe AspectJ security interceptor is very similar to the AOP Alliance security
interceptor discussed in the previous section. Indeed we will only discuss the
differences in this section.The AspectJ interceptor is named AspectJSecurityInterceptor. Unlike
the AOP Alliance security interceptor, which relies on the Spring application context to
weave in the security interceptor via proxying, the
AspectJSecurityInterceptor is weaved in via the AspectJ compiler. It
would not be uncommon to use both types of security interceptors in the same
application, with AspectJSecurityInterceptor being used for domain
object instance security and the AOP Alliance
MethodSecurityInterceptor being used for services layer
security.Let's first consider how the AspectJSecurityInterceptor is
configured in the Spring application context:
]]> As you can see, aside from the class name, the
AspectJSecurityInterceptor is exactly the same as the AOP Alliance
security interceptor. Indeed the two interceptors can share the same
securityMetadataSource, as the
SecurityMetadataSource works with
java.lang.reflect.Methods rather than an AOP library-specific class.
Of course, your access decisions have access to the relevant AOP library-specific
invocation (ie MethodInvocation or JoinPoint)
and as such can consider a range of addition criteria when making access decisions (such
as method arguments).Next you'll need to define an AspectJ aspect. For example:
package org.springframework.security.samples.aspectj;
import org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor;
import org.springframework.security.access.intercept.aspectj.AspectJCallback;
import org.springframework.beans.factory.InitializingBean;
public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
private AspectJSecurityInterceptor securityInterceptor;
pointcut domainObjectInstanceExecution(): target(PersistableEntity)
&& execution(public * *(..)) && !within(DomainObjectInstanceSecurityAspect);
Object around(): domainObjectInstanceExecution() {
if (this.securityInterceptor == null) {
return proceed();
}
AspectJCallback callback = new AspectJCallback() {
public Object proceedWithObject() {
return proceed();
}
};
return this.securityInterceptor.invoke(thisJoinPoint, callback);
}
public AspectJSecurityInterceptor getSecurityInterceptor() {
return securityInterceptor;
}
public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
this.securityInterceptor = securityInterceptor;
}
public void afterPropertiesSet() throws Exception {
if (this.securityInterceptor == null)
throw new IllegalArgumentException("securityInterceptor required");
}
}
}
In the above example, the security interceptor will be applied to every instance of
PersistableEntity, which is an abstract class not shown (you can use
any other class or pointcut expression you like). For those curious,
AspectJCallback is needed because the proceed();
statement has special meaning only within an around() body. The
AspectJSecurityInterceptor calls this anonymous
AspectJCallback class when it wants the target object to
continue.You will need to configure Spring to load the aspect and wire it with the
AspectJSecurityInterceptor. A bean declaration which achieves this is
shown below:
]]>
That's it! Now you can create your beans from anywhere within your application, using
whatever means you think fit (eg new Person();) and they will have
the security interceptor applied.