<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="secure-object-impls"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <info>
        <title>Secure Object Implementations</title>
    </info>
    <section xml:id="aop-alliance">
        <info>
            <title>AOP Alliance (MethodInvocation) Security Interceptor</title>
        </info>
        <para> Prior to Spring Security 2.0, securing <classname>MethodInvocation</classname>s
            needed quite a lot of boiler plate configuration. Now the recommended approach for
            method security is to use <link xlink:href="#ns-method-security">namespace
            configuration</link>. 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. </para>
        <para> Method security in enforced using a <classname>MethodSecurityInterceptor</classname>,
            which secures <classname>MethodInvocation</classname>s. Depending on the configuration
            approach, an interceptor may be specific to a single bean or shared between multiple
            beans. The interceptor uses a
            <interfacename>MethodSecurityMetadataSource</interfacename> instance to obtain the
            configuration attributes that apply to a particular method invocation.
            <classname>MapBasedMethodSecurityMetadataSource</classname> 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
            <literal>&lt;intercept-methods&gt;</literal> or <literal>&lt;protect-point&gt;</literal>
            elements. Other implementations will be used to handle annotation-based configuration. </para>
        <section>
            <title>Explicit MethodSecurityInterceptor Configuration</title>
            <para> You can of course configure a <classname>MethodSecurityIterceptor</classname>
                directly in your application context for use with one of Spring AOP's proxying
                mechanisms: <programlisting><![CDATA[
<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">
    <value>
      com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
      com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
    </value>
  </property>
</bean> ]]>
</programlisting></para>
        </section>
    </section>
    <section xml:id="aspectj">
        <info>
            <title>AspectJ (JoinPoint) Security Interceptor</title>
        </info>
        <para>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.</para>
        <para>The AspectJ interceptor is named <literal>AspectJSecurityInterceptor</literal>. Unlike
            the AOP Alliance security interceptor, which relies on the Spring application context to
            weave in the security interceptor via proxying, the
            <literal>AspectJSecurityInterceptor</literal> is weaved in via the AspectJ compiler. It
            would not be uncommon to use both types of security interceptors in the same
            application, with <literal>AspectJSecurityInterceptor</literal> being used for domain
            object instance security and the AOP Alliance
            <classname>MethodSecurityInterceptor</classname> being used for services layer
            security.</para>
        <para>Let's first consider how the <literal>AspectJSecurityInterceptor</literal> is
            configured in the Spring application context:</para>
        <programlisting><![CDATA[
<bean id="bankManagerSecurity" class=
    "org.springframework.security.access.intercept.aspectj.AspectJSecurityInterceptor">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="accessDecisionManager" ref="accessDecisionManager"/>
  <property name="afterInvocationManager" ref="afterInvocationManager"/>
  <property name="securityMetadataSource">
    <value>
        com.mycompany.BankManager.delete*=ROLE_SUPERVISOR
        com.mycompany.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR
    </value>
</property>
</bean>]]>        </programlisting>
        <para>As you can see, aside from the class name, the
            <literal>AspectJSecurityInterceptor</literal> is exactly the same as the AOP Alliance
            security interceptor. Indeed the two interceptors can share the same
            <literal>securityMetadataSource</literal>, as the
            <interfacename>SecurityMetadataSource</interfacename> works with
            <literal>java.lang.reflect.Method</literal>s rather than an AOP library-specific class.
            Of course, your access decisions have access to the relevant AOP library-specific
            invocation (ie <classname>MethodInvocation</classname> or <literal>JoinPoint</literal>)
            and as such can consider a range of addition criteria when making access decisions (such
            as method arguments).</para>
        <para>Next you'll need to define an AspectJ <literal>aspect</literal>. For example:</para>
        <programlisting language="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)
        &amp;&amp; execution(public * *(..)) &amp;&amp; !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");
        }
    }
}
</programlisting>
        <para>In the above example, the security interceptor will be applied to every instance of
            <literal>PersistableEntity</literal>, which is an abstract class not shown (you can use
            any other class or <literal>pointcut</literal> expression you like). For those curious,
            <literal>AspectJCallback</literal> is needed because the <literal>proceed();</literal>
            statement has special meaning only within an <literal>around()</literal> body. The
            <literal>AspectJSecurityInterceptor</literal> calls this anonymous
            <literal>AspectJCallback</literal> class when it wants the target object to
            continue.</para>
        <para>You will need to configure Spring to load the aspect and wire it with the
            <literal>AspectJSecurityInterceptor</literal>. A bean declaration which achieves this is
            shown below:</para>
        <programlisting><![CDATA[
<bean id="domainObjectInstanceSecurityAspect"
     class="security.samples.aspectj.DomainObjectInstanceSecurityAspect"
     factory-method="aspectOf">
  <property name="securityInterceptor" ref="bankManagerSecurity"/>
</bean>]]>
    </programlisting>
        <para>That's it! Now you can create your beans from anywhere within your application, using
            whatever means you think fit (eg <literal>new Person();</literal>) and they will have
            the security interceptor applied.</para>
    </section>
</chapter>
