Seam的安全框架(一)——授权

来源:互联网 发布:北京网络诈骗举报电话 编辑:程序博客网 时间:2024/05/19 09:14

 Seam安全API为安全访问组件、组件方法和页面提供了几种授权机制。本节将描述他们。一个需要注意的重要事项是如果你想使用任何高级特性(比如基于规则的权限),你需要在components.xml中配置它们以得到支持。

    1. 核心概念

    Seam安全的建立是围绕着用户被赋予角色并且/或者权限,允许它们执行那些在没有必要的安全特权就不能执行的操作的前提下的。Seam安全API提供的每一种授权机制都建立在角色和权限这些核心概念之上,这些概念拥有一个提供多种方式保护应用资源的易扩展的框架。

    1.1. 什么是角色?

    角色是被赋予某些特权,可以执行一个和多个应用中的动作的用户的一个 组 或 类别。简单的角色仅仅由一个名称组成(比如"admin","user","customer"等等)。可以将角色赋予用户(或者其他的角色),也可以被用来为方便分配指定的特权而创建用户的逻辑组。

    1.2. 什么是权限?

    权限是一种执行一个单独的、特定的动作的特权(有时是一次性的)。一个应用只使用权限是完全可能的,然而角色在给一组用户赋予权限是提供了更高级别的便利 性。权限的结构比角色稍复杂,主要由三个方面构成:目标、动作和接受者。权限的目标是一个对象(或者一个任意名称和类),允许指定的接受者(或用户)执行 这个对象的一个特定的动作。例如,用户“Bob”有权限删除customer对象。在这个例子中,权限目标是“customer”,权限动作是 “delete”,权限的接受者是“Bob”。

    本文中,权限通常以target:action这种形式表现(忽略了接受者,尽管实际上一个接受者是必须的)。

    2. 保护组件

    让我们以@Restrict注释来研究最简单的授权和组件安全为开端。

    @Restrict与类型安全的安全注释

    由于@Restrict注释支持EL表达式,使得该注释为保护组件方法提供强大并且灵活的方法,建议使用类型安全的等价物(以后描述),至少在编译期间是安全的。

    2.1. @Restrict注释

    使用@Restrict注释,可以在方法和类级别上保护Seam组件。如果一个方法和它声明类都使用了@Restrict注释,方法的约束将有更高的优先级(并且类约束将不起作用)。如果一个方法调用在安全检查使失败,按照Identity.checkRestriction()的约定,它将抛出一个异常(参见内联约束)。在组件类级别上的@Restrict注释等价于它每个方法都使用了这个注释。

    一个空的@Restrict意味着一个默认的权限检查:componentName:methodName。如下所示:

    @Name("account")

    public class AccountAction {

    @Restrict public void delete() {

    }

    }

    在这个例子中,调用delete()方法时需要的隐含权限是account:delete。与@Restrict("#{s:hasPermission('account','delete')}")这样写是等价的。现在,让我们看看另外一个例子:

    @Restrict @Name("account")

    public class AccountAction {

    public void insert() {

    }

    @Restrict("#{s:hasRole('admin')}")

    public void delete() {

    }

    }

    这次,组件类本身使用了@Restrict注释。这意味着任何没有重写@Restrict注释的方法都需要一个隐含的权限检查。在这个例子中,insert()方法需要一个account:insert权限,而delete()方法需要用户是"admin"角色的一个成员。

    在继续深入前,先解释一下上面看见的#{s:hasRole()}表达式。s:hasRole和s:hasPermission都是EL函数,贯穿整个安全API,这些函数能在任何EL表达式是使用。

    通过一个EL表达式,@Restrict注释的值可以引用存在于Seam上下文中的任何对象。这在为一个指定的对象实例执行权限检查是非常有用的。看这个例子:

    @Name("account")

    public class AccountAction {

    @In Account selectedAccount;

    @Restrict("#{s:hasPermission(selectedAccount,'modify')}")

    public void modify() {

    selectedAccount.modify();

    }

    }

    在这个例子中需要说明的有趣的一点是hasPermission()函数调用了selectedAccount方法的引用。该变量值将在Seam上下文中查找,并传递给Identity的hasPermission()方法,在本例中它将确定用户是否有必须的修改指定Account对象的权限。