Seam的安全框架授权(Authorization)(译) (一)

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

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

让我们以@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:hasRoles: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上下文中查找,并传递给IdentityhasPermission()方法,在本例中它将确定用户是否有必须的修改指定Account对象的权限。 有时它也可以在声明在代码中来执行安全检查,而不使用@Restrict注释。在这种情况下,简单的使用Identity.checkRestriction()来评估安全表达式,就像这样:
public void deleteCustomer() {

    Identity.instance().checkRestriction(
"#{s:hasPermission(selectedCustomer,'delete')}");

}
如果这个指定表达式评估后不为true,并且 也可以在Java代码中直接调用hasRole()hasPermission()方法:
if (!Identity.instance().hasRole("admin"))
     
throw new AuthorizationException("Must be admin to perform this action");

if (!Identity.instance().hasPermission("customer""create"))
     
throw new AuthorizationException("You may not create new customers");

作为一个优良设计的用户界面的指标之一就是用户不会看见它没有权限使用的选项。基于以上的用户的特权,使用非常一致的组件安全性EL表达式,Seam安全允许有条件的渲染 1)页面的区段和 2)独立的控件。

让我们看看一些界面安全的例子。首先,假设我们有一个登录表单,它只能在用户没有登录的时候被渲染。使用identity.isLoggedIn()特性,我们可以这样写:
<h:form class="loginForm" rendered="#{not identity.loggedIn}">
如果用户没有登录,那么登录表单将被渲染-到目前为止,非常简单。现在,假设页面上有一个菜单,它包含一些只能被是“manager”角色的用户访问的动作。可以写成这样:
<h:outputLink action="#{reports.listManagerReports}" rendered="#{s:hasRole('manager')}">
    Manager Reports
</h:outputLink>
这也相当直截了当。如果用户不是manager角色的成员,那么这个outputlink将不会被渲染。rendered属性通常是控件本身使用,或者是一个被包围的<s:div><s:span>控件。

现在看看一些更复杂的。假设你有一个h:dataTable控件,其中的数据列表中你希望依靠用户的权限来决定是否被渲染而显示。s:hasPermission这个EL函数允许我们传递一个可以决定是否用户拥有要求的权限的对象参数。这样的被保护的dataTable可能像这样:

<h:dataTable value="#{clients}" var="cl">
    
<h:column>
        
<f:facet name="header">Name</f:facet>
        #{cl.name}
    
</h:column>
    
<h:column>
        
<f:facet name="header">City</f:facet>
        #{cl.city}
    
</h:column>
    
<h:column>
        
<f:facet name="header">Action</f:facet>
        
<s:link value="Modify Client" action="#{clientAction.modify}"
                rendered
="#{s:hasPermission(cl,'modify')"/>
        
<s:link value="Delete Client" action="#{clientAction.delete}"
                rendered
="#{s:hasPermission(cl,'delete')"/>
    
</h:column>
</h:dataTable>





原文地址:https://www.cnblogs.com/rgbw/p/1566499.html