123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- [[secure-object-impls]]
- = Secure Object Implementations
- This section covers how Spring Security handles Secure Object implementations.
- [[aop-alliance]]
- == AOP Alliance (MethodInvocation) Security Interceptor
- Prior to Spring Security 2.0, securing `MethodInvocation` instances needed a lot of boiler plate configuration.
- Now the recommended approach for method security is to use xref:servlet/configuration/xml-namespace.adoc#ns-method-security[namespace configuration].
- This way, the method security infrastructure beans are configured automatically for you, so you need not know about the implementation classes.
- We provide only a quick overview of the classes that are involved here.
- Method security is enforced by using a `MethodSecurityInterceptor`, which secures `MethodInvocation` instances.
- 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 are used to handle annotation-based configuration.
- === Explicit MethodSecurityInterceptor Configuration
- You can 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.
- We discuss only 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 through proxying, the `AspectJSecurityInterceptor` is woven in through 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.
- We 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>
- ----
- The two interceptors can share the same `securityMetadataSource`, as the `SecurityMetadataSource` works with `java.lang.reflect.Method` instances rather than an AOP library-specific class.
- Your access decisions have access to the relevant AOP library-specific invocation (`MethodInvocation` or `JoinPoint`) and can consider a range of additional criteria (such as method arguments) when making access decisions.
- Next, you need to define an AspectJ `aspect`, as the following example shows:
- [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 preceding example, the security interceptor is 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 need to configure Spring to load the aspect and wire it with the `AspectJSecurityInterceptor`.
- The following example shows a bean declaration that achieves this:
- [source,xml]
- ----
- <bean id="domainObjectInstanceSecurityAspect"
- class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
- factory-method="aspectOf">
- <property name="securityInterceptor" ref="bankManagerSecurity"/>
- </bean>
- ----
- Now you can create your beans from anywhere within your application, using whatever means you think fit (e.g. `new Person();`), and they have the security interceptor applied.
|