123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- [[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 <<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.
|