<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="el-access"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>Expression-Based Access Control</title>
    <para> Spring Security 3.0 introduced the ability to use Spring EL expressions as an
        authorization mechanism in addition to the simple use of configuration attributes and
        access-decision voters which have seen before. Expression-based access control is built on
        the same architecture but allows complicated boolean logic to be encapsulated in a single
        expression.</para>
    <section>
        <title>Overview</title>
        <para>Spring Security uses Spring EL for expression support and you should look at how that
            works if you are interested in understanding the topic in more depth. Expressions are
            evaluated with a <quote>root object</quote> as part of the evaluation context. Spring
            Security uses specific classes for web and method security as the root object, in order
            to provide built-in expressions and access to values such as the current
            principal.</para>
        <section xml:id="el-common-built-in">
            <title>Common Built-In Expressions</title>
            <para>The base class for expression root objects is
                <classname>SecurityExpressionRoot</classname>. This provides some common expressions
                which are available in both web and method security.</para>
            <table frame="none">
                <title>Common built-in expressions</title>
                <tgroup cols="2">
                    <colspec colname="c1" colnum="1" colwidth="1.0*"/>
                    <colspec colname="c2" colnum="2" colwidth="2.0*"/>
                    <thead>
                        <row>
                            <entry>Expression</entry>
                            <entry>Description</entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry><literal>hasRole([role])</literal></entry>
                            <entry>Returns <literal>true</literal> if the current principal has the
                                specified role.</entry>
                        </row>
                        <row>
                            <entry><literal>hasAnyRole([role1,role2])</literal></entry>
                            <entry>Returns <literal>true</literal> if the current principal has any
                                of the supplied roles (given as a comma-separated list of
                                strings)</entry>
                        </row>
                        <row>
                            <entry><literal>principal</literal></entry>
                            <entry>Allows direct access to the principal object representing the
                                current user</entry>
                        </row>
                        <row>
                            <entry><literal>authentication</literal></entry>
                            <entry>Allows direct access to the current
                                <interfacename>Authentication</interfacename> object obtained from
                                the <interfacename>SecurityContext</interfacename></entry>
                        </row>
                        <row>
                            <entry><literal>permitAll</literal></entry>
                            <entry>Always evaluates to <literal>true</literal></entry>
                        </row>
                        <row>
                            <entry><literal>denyAll</literal></entry>
                            <entry>Always evaluates to <literal>false</literal></entry>
                        </row>
                        <row>
                            <entry><literal>isAnonymous()</literal></entry>
                            <entry>Returns <literal>true</literal> if the current principal is an
                                anonymous user</entry>
                        </row>
                        <row>
                            <entry><literal>isRememberMe()</literal></entry>
                            <entry>Returns <literal>true</literal> if the current principal is a
                                remember-me user</entry>
                        </row>
                        <row>
                            <entry><literal>isAuthenticated()</literal></entry>
                            <entry>Returns <literal>true</literal> if the user is not
                                anonymous</entry>
                        </row>
                        <row>
                            <entry><literal>isFullyAuthenticated()</literal></entry>
                            <entry>Returns <literal>true</literal> if the user is not an anonymous
                                or a remember-me user</entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>
        </section>
    </section>
    <section xml:id="el-access-web">
        <title>Web Security Expressions</title>
        <para> To use expressions to secure individual URLs, you would first need to set the
            <literal>use-expressions</literal> attribute in the <literal>&lt;http></literal> element
            to <literal>true</literal>. Spring Security will then expect the
            <literal>access</literal> attributes of the <literal>&lt;intercept-url></literal>
            elements to contain Spring EL expressions. The expressions should evaluate to a boolean,
            defining whether access should be allowed or not. For example:<programlisting language="xml"><![CDATA[
  <http use-expressions="true">
    <intercept-url pattern="/admin*"
        access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
    ...
  </http>
]]></programlisting>Here we have defined that the <quote>admin</quote> area of an application
            (defined by the URL pattern) should only be available to users who have the granted
            authority <quote>admin</quote> and whose IP address matches a local subnet. We've
            already seen the built-in <literal>hasRole</literal> expression in the previous section.
            The expression <literal>hasIpAddress</literal> is an additional built-in expression
            which is specific to web security. It is defined by the
            <classname>WebSecurityExpressionRoot</classname> class, an instance of which is used as
            the expression root object when evaluation web-access expressions. This object also
            directly exposed the <interfacename>HttpServletRequest</interfacename> object under the
            name <literal>request</literal> so you can invoke the request directly in an
            expression.</para>
        <para>If expressions are being used, a <classname>WebExpressionVoter</classname> will be
            added to the <interfacename>AccessDecisionManager</interfacename> which is used by the
            namespace. So if you aren't using the namespace and want to use expressions, you will
            have to add one of these to your configuration.</para>
    </section>
    <section>
        <title>Method Security Expressions</title>
        <para>Method security is a bit more complicated than a simple allow or deny rule. Spring
            Security 3.0 introduced some new annotations in order to allow comprehensive support for
            the use of expressions.</para>
        <section xml:id="el-pre-post-annotations">
            <title><literal>@Pre</literal> and <literal>@Post</literal> Annotations</title>
            <para>There are four annotations which support expression attributes to allow pre and
                post-invocation authorization checks and also to support filtering of submitted
                collection arguments or return values. They are <literal>@PreAuthorize</literal>,
                <literal>@PreFilter</literal>, <literal>@PostAuthorize</literal> and
                <literal>@PostFilter</literal>. Their use is enabled through the
                <literal>global-method-security</literal> namespace
                element:<programlisting language="xml"><![CDATA[<global-method-security pre-post-annotations="enabled"/>]]></programlisting></para>
            <section>
                <title>Access Control using <literal>@PreAuthorize</literal> and
                    <literal>@PostAuthorize</literal></title>
                <para>The most obviously useful annotation is <literal>@PreAuthorize</literal> which
                    decides whether a method can actually be invoked or not. For example (from the
                    <quote>Contacts</quote> sample
                    application)<programlisting language="java">
 @PreAuthorize("hasRole('ROLE_USER')")
 public void create(Contact contact);</programlisting>which
                    means that access will only be allowed for users with the role "ROLE_USER".
                    Obviously the same thing could easily be achieved using a traditional
                    configuration and a simple configuration attribute for the required role. But
                    what
                    about:<programlisting language="java">
 @PreAuthorize("hasPermission(#contact, 'admin')")
 public void deletePermission(Contact contact, Sid recipient, Permission permission);</programlisting>Here
                    we're actually using a method argument as part of the expression to decide
                    whether the current user has the <quote>admin</quote>permission for the given
                    contact. The built-in <literal>hasPermission()</literal> expression is linked
                    into the Spring Security ACL module through the application context, as we'll
                    <link xlink:href="#el-permission-evaluator">see below</link>. You can access any
                    of the method arguments by name as expression variables, provided your code has
                    debug information compiled in. Any Spring-EL functionality is available within
                    the expression, so you can also access properties on the arguments. For example,
                    if you wanted a particular method to only allow access to a user whose username
                    matched that of the contact, you could write</para>
                <programlisting language="java">
 @PreAuthorize("#contact.name == authentication.name")
 public void doSomething(Contact contact);</programlisting>
                <para>Here we are accessing another built–in expression, <literal>authentication</literal>,
                    which is the <interfacename>Authentication</interfacename> stored in the
                    security context. You can also access its <quote>principal</quote> property
                    directly, using the expression <literal>principal</literal>. The value will
                    often be a <interfacename>UserDetails</interfacename> instance, so you might use an
                    expression like <literal>principal.username</literal> or
                    <literal>principal.enabled</literal>.</para>
                <para>Less commonly, you may wish to perform an access-control check after the
                    method has been invoked. This can be achieved using the
                    <literal>@PostAuthorize</literal> annotation. To access the return value from a
                    method, use the built–in name <literal>returnObject</literal> in the
                    expression.</para>
            </section>
            <section>
                <title>Filtering using <literal>@PreFilter</literal> and
                    <literal>@PostFilter</literal></title>
                <para>As you may already be aware, Spring Security supports filtering of collections
                    and arrays and this can now be achieved using expressions. This is most commonly
                    performed on the return value of a method. For
                    example:<programlisting language="java">  @PreAuthorize("hasRole('ROLE_USER')")
  @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
  public List&lt;Contact> getAll();</programlisting>When
                    using the <literal>@PostFilter</literal> annotation, Spring Security iterates
                    through the returned collection and removes any elements for which the supplied
                    expression is false. The name <literal>filterObject</literal> refers to the
                    current object in the collection. You can also filter before the method call,
                    using <literal>@PreFilter</literal>, though this is a less common requirement.
                    The syntax is just the same, but if there is more than one argument which is a
                    collection type then you have to select one by name using the
                    <literal>filterTarget</literal> property of this annotation.</para>
                <para>Note that filtering is obviously not a substitute for tuning your data
                    retrieval queries. If you are filtering large collections and removing many of
                    the entries then this is likely to be inefficient.</para>
            </section>
        </section>
        <section xml:id="el-method-built-in">
            <title>Built-In Expressions</title>
            <para>There are some built-in expressions which are specific to method security, which
                we have already seen in use above. The <literal>filterTarget</literal> and
                <literal>returnValue</literal> values are simple enough, but the use of the
                <literal>hasPermission()</literal> expression warrants a closer look.</para>
            <section xml:id="el-permission-evaluator">
                <title>The <interfacename>PermissionEvaluator</interfacename> interface</title>
                <para><literal>hasPermission()</literal> expressions are delegated to an instance of
                    <interfacename>PermissionEvaluator</interfacename>. It is intended to bridge
                    between the expression system and Spring Security's ACL system, allowing you to
                    specify authorization constraints on domain objects, based on abstract
                    permissions. It has no explicit dependencies on the ACL module, so you could
                    swap that out for an alternative implementation if required. The interface has
                    two methods:
                    <programlisting language="java">
 boolean hasPermission(Authentication authentication, Object targetDomainObject,
                             Object permission);

 boolean hasPermission(Authentication authentication, Serializable targetId,
                              String targetType, Object permission);
</programlisting>which
                    map directly to the available versions of the expression, with the exception
                    that the first argument (the <interfacename>Authentication</interfacename>
                    object) is not supplied. The first is used in situations where the domain
                    object, to which access is being controlled, is already loaded. Then expression
                    will return true if the current user has the given permission for that object.
                    The second version is used in cases where the object is not loaded, but its
                    identifier is known. An abstract <quote>type</quote> specifier for the domain
                    object is also required, allowing the correct ACL permissions to be loaded. This
                    has traditionally been the Java class of the object, but does not have to be as
                    long as it is consistent with how the permissions are loaded.</para>
                <para>To use <literal>hasPermission()</literal> expressions, you have to explicitly
                    configure a <interfacename>PermissionEvaluator</interfacename> in your
                    application context. This would look something like this: <programlisting language="xml"> <![CDATA[
<security:global-method-security pre-post-annotations="enabled">
  <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="expressionHandler" class=
  "org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
     <property name="permissionEvaluator" ref="myPermissionEvaluator"/>
</bean>]]></programlisting>Where <literal>myPermissionEvaluator</literal> is the bean which
                    implements <interfacename>PermissionEvaluator</interfacename>. Usually this will
                    be the implementation from the ACL module which is called
                    <classname>AclPermissionEvaluator</classname>. See the <quote>Contacts</quote>
                    sample application configuration for more details.</para>
            </section>
        </section>
    </section>
</chapter>
