Antora
mkdir -p docs/modules/ROOT/ mkdir -p docs/modules/ROOT/pages/ git checkout antora-2.x docs/antora.yml git checkout antora-2.x docs/modules/ROOT/nav.adoc mv docs/manual/src/docs/asciidoc/images docs/modules/ROOT/ mv docs/manual/src/docs/asciidoc/_includes/* docs/modules/ROOT/pages/ cp ~/code/rwinch/spring-reference/*antora* ~/code/spring-projects/spring-security/ mv docs/modules/ROOT/pages/about docs/modules/ROOT/pages/overview
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
|
||||
[[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.
|
||||
Reference in New Issue
Block a user