You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
6.7 KiB
143 lines
6.7 KiB
|
|
[[secure-object-impls]] |
|
= Secure Object Implementations |
|
|
|
[[aop-alliance]] |
|
== AOP Alliance (MethodInvocation) Security Interceptor |
|
Prior to Spring Security 2.0, securing ``MethodInvocation``s needed quite a lot of boiler plate configuration. |
|
Now the recommended approach for method security is to use xref:servlet/namespace/index.adoc#ns-method-security[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 is enforced using a `MethodSecurityInterceptor`, which secures ``MethodInvocation``s. |
|
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 `MethodSecurityInterceptor` directly in your application context for use with one of Spring AOP's proxying mechanisms: |
|
|
|
[source,xml] |
|
---- |
|
|
|
<bean id="bankManagerSecurity" class= |
|
"org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor"> |
|
<property name="authenticationManager" ref="authenticationManager"/> |
|
<property name="accessDecisionManager" ref="accessDecisionManager"/> |
|
<property name="afterInvocationManager" ref="afterInvocationManager"/> |
|
<property name="securityMetadataSource"> |
|
<sec:method-security-metadata-source> |
|
<sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/> |
|
<sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/> |
|
</sec:method-security-metadata-source> |
|
</property> |
|
</bean> |
|
---- |
|
|
|
[[aspectj]] |
|
== AspectJ (JoinPoint) Security Interceptor |
|
The 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: |
|
|
|
|
|
[source,xml] |
|
---- |
|
|
|
<bean id="bankManagerSecurity" class= |
|
"org.springframework.security.access.intercept.aspectj.AspectJMethodSecurityInterceptor"> |
|
<property name="authenticationManager" ref="authenticationManager"/> |
|
<property name="accessDecisionManager" ref="accessDecisionManager"/> |
|
<property name="afterInvocationManager" ref="afterInvocationManager"/> |
|
<property name="securityMetadataSource"> |
|
<sec:method-security-metadata-source> |
|
<sec:protect method="com.mycompany.BankManager.delete*" access="ROLE_SUPERVISOR"/> |
|
<sec:protect method="com.mycompany.BankManager.getBalance" access="ROLE_TELLER,ROLE_SUPERVISOR"/> |
|
</sec:method-security-metadata-source> |
|
</property> |
|
</bean> |
|
---- |
|
|
|
|
|
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.Method``s 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: |
|
|
|
|
|
[source,java] |
|
---- |
|
|
|
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: |
|
|
|
|
|
[source,xml] |
|
---- |
|
|
|
<bean id="domainObjectInstanceSecurityAspect" |
|
class="security.samples.aspectj.DomainObjectInstanceSecurityAspect" |
|
factory-method="aspectOf"> |
|
<property name="securityInterceptor" ref="bankManagerSecurity"/> |
|
</bean> |
|
---- |
|
|
|
|
|
That's it! |
|
Now you can create your beans from anywhere within your application, using whatever means you think fit (e.g. `new Person();`) and they will have the security interceptor applied.
|
|
|