diff --git a/docs/manual/src/docbook/el-access.xml b/docs/manual/src/docbook/el-access.xml index 09417c1604..a3102dea4c 100644 --- a/docs/manual/src/docbook/el-access.xml +++ b/docs/manual/src/docbook/el-access.xml @@ -6,7 +6,87 @@ 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. + expression. +
+ Overview + 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 root object 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. +
+ Common Built-In Expressions + The base class for expression root objects is + SecurityExpressionRoot. This provides some common + expressions which are available in both web and method security. + + Common built-in expressions + + + + + + Expression + Description + + + + + hasRole([role]) + Returns true if the current principal has the + specified role. + + + hasAnyRole([role1,role2]) + Returns true if the current principal has any + of the supplied roles (given as a comma-separated list of + strings) + + + principal + Allows direct access to the principal object representing the + current user + + + authentication + Allows direct access to the current + Authentication object obtained + from the SecurityContext + + + permitAll + Always evaluates to true + + + denyAll + Always evaluates to false + + + isAnonymous() + Returns true if the current principal is an + anonymous user + + + isRememberMe() + Returns true if the current principal is a + remember-me user + + + isAuthenticated() + Returns true if the user is not + anonymous + + + isFullyAuthenticated() + Returns true if the user is not an anonyous or + a remember-me user + + + +
+
+
Web Security Expressions To use expressions to secure individual URLs, you would first need to set the @@ -20,16 +100,16 @@ access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/> ... -]]>Here we have defined that the "admin" area of an application should only be - available to users who have the granted authority admin and whose IP - address matches a local subnet. The expressions hasRole and - hasIpAddress are both built in expressions, which are defined by - the WebSecurityExpressionRoot class, an instance of which is used - as the expression root object when evaluation web-access expressions. See the - documentation for Spring EL in the main Spring Framework reference if you want to know - more about the details of expression evaluation. This object also directly exposed the - HttpServletRequest object under the name - request so you can invoke the request directly in an +]]>Here we have defined that the admin area of an application + (defined by the URL pattern) should only be available to users who have the granted + authority admin and whose IP address matches a local subnet. We've + already seen the built-in hasRole expression in the previous section. + The expression hasIpAddress is an additional built-in expression + which is specific to web security. It is defined by the + WebSecurityExpressionRoot class, an instance of which is used + as the expression root object when evaluation web-access expressions. This object also + directly exposed the HttpServletRequest object under the + name request so you can invoke the request directly in an expression. If expressions are being used, a WebExpressionVoter will be added to the AccessDecisionManager which is used by the @@ -38,11 +118,76 @@
Method Security Expressions - Method security expressions in Spring Security 3.0 are supported through the use of - special annotations which allow pre and post-invocation authorization checks. - Expressions can also be used to filter collections or arrays, based on the permissions - of the principal invoking the method. Values can be removed from a collection argument - prior to the invocation of the method or, post-invocation, a returned collection can be - filtered to remove items to which the user should not have access. + 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. +
+ <literal>@Pre</literal> and <literal>@Post</literal> Annotations + 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 @PreAuthorize, + @PreFilter, @PostAuthorize and + @PostFilter. Their use is enabled through the + global-method-security namespace + element:]]> +
+ Access Control using <literal>@PreAuthorize</literal> and + <literal>@PostAuthorize</literal> + The most obviously useful annotation is @PreAuthorize which + decides whether a method can actually be invoked or not. For example (from the + Contacts sample + application) @PreAuthorize("hasRole('ROLE_USER')") + public void create(Contact contact);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: @PreAuthorize("hasPermission(#contact, 'admin')") + public void deletePermission(Contact contact, Sid recipient, Permission permission);Here + we're actually using a method argument as part of the expression to decide + whether the current user has the adminpermission for the given + contact. The built-in hasPermission() expression is linked + into the Spring Security ACL module through the application context. 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 + @PreAuthorize("#contact.name == principal.name)") + public void doSomething(Contact contact); + Here we are accessing another built–in expression, which is the + principal of the current Spring Security + Authentication object obtained from the + security context. You can also access the + Authentication object itself directly using + the expression name authentication. + Less commonly, you may wish to perform an access-control check after the + method has been invoked. This can be achieved using the + @PostAuthorize annotation. To access the return value + from a method, use the built–in name returnObject in the + expression. +
+
+ Filtering using <literal>@PreFilter</literal> and + <literal>@PostFilter</literal> + 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: @PreAuthorize("hasRole('ROLE_USER')") + @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')") + public List<Contact> getAll();When + using the @PostFilter annotation, Spring Security iterates + through the returned collection and removes any elements for which the supplied + expression is false. The name filterObject refers to the + current object in the collection. You can also filter before the method call, + using @PreFilter, 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 + filterTarget property of this annotation. + 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. +
+