Let's start by examining the simplest form of authorization, component security, starting with the @Restrict
annotation.
Seam components may be secured either at the method or the class level, using the @Restrict
annotation. If both a method and it's declaring class are annotated with @Restrict
, the method restriction will take precedence (and the class restriction will not apply). If a method invocation fails a security check, then an exception will be thrown as per the contract for Identity.checkRestriction()
(see Inline Restrictions). A @Restrict
on just the component class itself is equivalent to adding @Restrict
to each of its methods.
An empty @Restrict
implies a permission check of componentName:methodName
. Take for example the following component method:
@Name("account")
public class AccountAction {
@Restrict public void delete() {
...
}
}
In this example, the implied permission required to call the delete()
method is account:delete
. The equivalent of this would be to write @Restrict("#{s:hasPermission('account','delete',null)}")
. Now let's look at another example:
@Restrict @Name("account")
public class AccountAction {
public void insert() {
...
}
@Restrict("#{s:hasRole('admin')}")
public void delete() {
...
}
}
This time, the component class itself is annotated with @Restrict
. This means that any methods without an overriding @Restrict
annotation require an implicit permission check. In the case of this example, the insert()
method requires a permission of account:insert
, while the delete()
method requires that the user is a member of the admin
role.
Before we go any further, let's address the #{s:hasRole()}
expression seen in the above example. Both s:hasRole
and s:hasPermission
are EL functions, which delegate to the correspondingly named methods of the Identity
class. These functions can be used within any EL expression throughout the entirety of the security API.
Being an EL expression, the value of the @Restrict
annotation may reference any objects that exist within a Seam context. This is extremely useful when performing permission checks for a specific object instance. Look at this example:
@Name("account")
public class AccountAction {
@In Account selectedAccount;
@Restrict("#{s:hasPermission('account','modify',selectedAccount)}")
public void modify() {
selectedAccount.modify();
}
}
The interesting thing to note from this example is the reference to selectedAccount
seen within the hasPermission()
function call. The value of this variable will be looked up from within the Seam context, and passed to the hasPermission()
method in Identity
, which in this case can then determine if the user has the required permission for modifying the specified Account
object.