`

seam2.1权限验证(15.5)@Restrict注解 (一)

    博客分类:
  • Seam
阅读更多
15.5. 错误消息安全API内嵌了针对各种安全相关操作的faces messages。下面这个表里面列出了在message.properties文件里面修改这些消息的message keys。如果想要禁用这些消息,只要在资源文件里面将这些错误消息的值置空就ok了。
Table 15.6. 安全消息

Message Key描述org.jboss.seam.loginSuccessful不用多说了,看字面就知道什么意思了org.jboss.seam.loginFailed org.jboss.seam.NotLoggedIn org.jboss.seam.AlreadyLoggedIn 

15.6. 验证(Authorization)Seam Security API里面提供了很多权限验证的方法,无论是component、component method、或者页面上,你随时都可以进行权限验证相关的处理。这一节介绍了所有权限验证方面的内容。如果你需要使用任何高级特性(例如基于规则的权限验证),你一定要记住在components.xml文件里面指明(配置方法见前面的章节)。
15.6.1. 核心概念Seam安全模块就是用来让那些被授予了角色和(或)权限的人能够进行某些操作,并且阻止那些没有被授权的人进行这些相应操作的。Seam安全接口提供了验证用户权限的各种方法,这些方法都基于角色/权限概念。通过扩展框架功能,你还能同时使用多种方式来对程序的安全进行控制。
15.6.1.1. 什么是角色?一个角色就是一个组或者说是一种类型。这个组包含了用户可能会被赋予的一组权限(一组被许可在程序中进行的操作集合)。角色的结构很简单,仅仅由一个名称组成,例如“admin”、“user”、“customer”等。角色可以被赋予某个用户(有时也可能将角色赋予某个角色),并且可以用来对拥有相似操作权限的用户分组。



15.6.1.2. 什么是权限?权限就是进行某个操作(有时是一次性操作)的权利。在编写一个程序的时候,你完全可以只用权限来控制所有操作(这里指不适用角色的概念),但是有了角色,你就能进行一些更加“高级”的操作,例如将一组很多个权限同时赋予用户。权限比角色的结构稍微复杂点,主要包含三个属性:一个目标(target)、一个操作(action)、一个接受者(recipient)。权限的目标指接受者(或者说用户)被授权进行某一特殊操作的对象(可以是一个字符串的名称或者一个class)。例如,一个名叫Bob的用户拥有删除客户的权限,那么,删除用户这个权限的对象(target)为“客户”,权限的操作(action)为“删除”,权限的接受者(recipient)为“Bob”这个人。



在这个文档里面,我们通常将一个权限通过这种方式来表现:target:action(我们在这里忽略了接受者,但是在实际应用当中,接受者是必须的) 。
15.6.2. components验证让我们从最简单的验证方式开始——components验证。首先是@Restrict注解。
注意:@Restrict vs Typesafe security annotations
@Restrict能够使用EL表达式,所以它能够提供功能完善且灵活的验证方法。我们建议使用到的EL表达式应该是类型安全的,起码在编译的时候要保证它的安全。
15.6.2.1. @Restrict注解Seam组件可以通过使用添加@Restrict注解的方式来实现方法级别或者类级别的安全控制。如果一个方法和这个方法所在类同时使用了@Restrict注解,那么方法级别的安全限制优先级更高(意味着类级别的限制不起作用)。如果在方法上验证失败,那么与执行Identity.checkRestriction()方法一样抛出一个异常(参考相关的文档)。把@Restrict加在一个组件类上,相当于将这个约束加在了这个类的所有方法上。
一个空的@Restrict约束默认使用componentName:methodName作为权限的名称。例如以下这段代码:
Java代码

@Name("account")  
public class AccountAction {  
    @Restrict public void delete() { ... }  

@Name("account")public class AccountAction {    @Restrict public void delete() { ... }}

在这个例子中,默认调用delete()方法需要account:delete权限。效果与
Java代码

@Restrict("#{s:hasPermission('account','delete')}") 
@Restrict("#{s:hasPermission('account','delete')}")
相等。

再来看下面这段代码:
Java代码

@Restrict @Name("account")  
public class AccountAction {  
    public void insert() {  
      ...  
    }  
    @Restrict("#{s:hasRole('admin')}")  
    public void 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表达式,分别对应Identity类里面的方法。这个方法能够用在所有EL表达式中,并且会用在所有安全验证相关的部分。
作为一个EL表达式,@Restrict注解的值可以关联到任何一个Seam上下文中存在的对象上。这在对某个具体的实例进行权限验证的时候非常有用:
面这个例子中,有一段代码比较有趣。就是在hasPermission()方法内部使用到了selectedAccount对象。此时,Seam会到上下文中寻找这个对象实例,并且将它传递给Identity对象的hasPermission()方法。这样就能判断出当前用户是否有权限来修改当前被注入的这个Account对象。
Java代码

@Name("account")  
public class AccountAction {  
    @In Account selectedAccount;  
    @Restrict("#{s:hasPermission(selectedAccount,'modify')}")  
    public void modify() {  
        selectedAccount.modify();  
    }  

@Name("account")public class AccountAction {    @In Account selectedAccount;    @Restrict("#{s:hasPermission(selectedAccount,'modify')}")    public void modify() {        selectedAccount.modify();    }}
15.6.2.2. 内部约束(Inline restrictions)有的时候你可能会需要在某个方法的代码内部检查权限,这样就无法使用@Restrict注解。这种情况下,你就需要用到Identity.checkRestriction()方法来执行一个与安全有关的表达式,例如:
Java代码

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

public void deleteCustomer() {    Identity.instance().checkRestriction("#{s:hasPermission(selectedCustomer,'delete')}");}
如果表达式未返回true则:
用户没有登录——抛出NotLoggedInException异常,
用户已经登录——抛出AuthorizationException异常。
同样的,你也可以在任何Java代码中使用hasRole()和hasPersmission()方法。
Java代码

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"); 
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");
15.6.3. 程序界面中的安全控制(Security in the user interface)一个良好的用户界面设计需要符合一个特征,用户应该只看见他所能操作的部分,而用户没有权限看见或者没有权限进行操作的按钮链接等,不应该显示出来。Seam提供了两种根据权限控制界面显示内容的方法:
1)根据权限判断页面是否显示,
2)根据权限判断界面中的某个控件是否显示。这两种控制都使用EL表达式来判断。
我们来看几个权限控制的例子。
首先,一个登录表单需要只有当用户没有登录的时候才能看见。如果用户已经登录,那么就不需要显示登录表单。这个功能可以使用identity.isLoggedIn()属性来判断,在页面上,我们可以写成这样:
Xml代码

<h:form class="loginForm" rendered="#{not identity.loggedIn}"> 
<h:form class="loginForm" rendered="#{not identity.loggedIn}">
这种控制方式非常直观,看见代码的字面意思就应该能明白。下面,我们假设页面上有个显示所有报表的链接,这个链接只有当用户拥有manager角色的时候才能看见。我们在页面上可以这么写:
Xml代码

<h:outputLink action="#{reports.listManagerReports}" rendered="#{s:hasRole('manager')}"> 
    Manager Reports  
</h:outputLink> 
<h:outputLink action="#{reports.listManagerReports}" rendered="#{s:hasRole('manager')}">    Manager Reports</h:outputLink>
这段代码也很直观。如果用户没有manager角色,那么这个链接就不会显示。通常rendered属性可以直接写在具体的标签内部,但是根据实际情况,也可以将它写在某个父标签上,例如<s:div>或<s:span>。
现在,我们来看一个复杂点的例子。假设页面上有一个h:dataTable,用于显示一个记录列表。表格的最后一列用来显示对当前记录的操作链接,这个链接需要根据用户拥有的权限来判断是否显示。s:hasPermission表达式允许我们将当前行的记录作为参数传入权限判断函数,并根据传入的对象以及当前登录的用户来判断是否显示。下面就是这个表格的代码:
Xml代码

<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> 
<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>
15.6.4. 页面安全控制(Securing pages)页面安全控制需要程序里面有pages.xml文件,不过配置代码非常简单。只需要在page标签内部添加一个对象就能够实现安全控制。如果restrict对象没有任何属性或者子对象,那么默认情况下,来自non-faces (GET)的请求会需要权限/viewId.xhtml:render, JSF postback(来自表单提交方式)的请求会需要权限/viewId.xhtml:restore。此外,如果想要指定约束规则,那么只要写出标准的安全验证表达式即可。下面是几个例子:
Xml代码

<page view-id="/settings.xhtml"> 
    <restrict/> 
</page> 
<page view-id="/settings.xhtml">    <restrict/></page>

Xml代码

<page view-id="/reports.xhtml"> 
    <restrict>#{s:hasRole('admin')}</restrict> 
</page> 
分享到:
评论

相关推荐

    seam2.1说明文档

    在 Seam 2.1 中,最显著的变化之一就是增强了安全性方面的功能,尤其是在用户权限验证机制上。这一版本不仅提供了更为精细的权限控制选项,还增加了对最新安全标准的支持,如更严格的密码策略和会话管理机制等。 ##...

    seam 2.1 参考手册

    - **Annotation的支持**:Seam 2.1支持在Wicket内部类中使用注解,这为开发者提供了更多的灵活性来组织代码结构。 - **业务流程管理**:通过Seam 2.1,开发者可以在Wicket应用中更好地控制业务流程管理任务,例如...

    Seam 2.1 安全模块框架

    3. **权限验证**:Seam 包含一个广泛适用的权限验证框架,支持基于角色的访问控制(RBAC)、持久化权限设置以及规则驱动的权限决策。这使得开发者可以根据业务逻辑创建自定义的安全策略。 4. **权限管理**:Seam ...

    接上篇(seam登录时的权限验证)之“seam基于数据库的权限验证”

    此外,还可以使用Seam的`@Restrict`注解进行更细粒度的控制。 3. **数据库设计**:为了实现基于数据库的权限管理,我们需要设计一个包含用户、角色和权限关系的数据库模型。通常,会有一个`User`表存储用户信息,一...

    基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》全书

    ### 基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》全书知识点概览 #### 一、Seam框架简介 Seam框架是JBoss组织推出的一个开源项目,旨在简化企业级应用开发,通过...

    jboss-seam2.1

    Seam 是一种业级 企 Java 的应规用程序框架。它的灵感源自下列原 : 只有一种“工具” Seam为 应 业务业业 义 种统 组 你的 用程序中所有的 定 了一 一的 件模型。 Seam组件可能是 态义 关关 态 有状 的,包含与几...

    Jboss seam2.1版本开发参考文档

    ### JBoss Seam 2.1版本开发参考知识点 #### 一、JBoss Seam 框架简介 **JBoss Seam** 是一个企业级Java Web应用框架,它简化了基于Java平台的应用程序开发过程。该框架提供了强大的上下文管理功能、会话管理、...

    基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》摘要

    ### 基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》摘要分析 #### 核心概念:Seam框架概述 Seam框架是一款革命性的Web应用开发框架,它将标准的Java EE技术与一系列...

    seam的注解和标签

    - `@Name`: 这是Seam的核心注解,用于为组件定义一个唯一的名字。这个名字可以在JSF视图、表达式语言(EL)或者Seam的事件系统中引用。 - `@In`: 用于注入依赖。这相当于Spring框架中的@Autowired。你可以指定...

    jboss-seam 注解

    在JBoss Seam框架中,`@Name`注解主要用于定义一个Seam组件。为了确保组件能够被正确识别与使用,每个Seam组件都必须拥有一个唯一的名称标识,即通过`@Name`来指定。例如: ```java @Name("componentName") public ...

    jboss seam 2.0 中文手册

    整理自jboss seam 中文站,压缩为chm格式,便于广大jboss seam爱好者阅读,所有版权归jboss seam中文站所有。

    seam 注解 pdf

    #### 一、Seam框架概述与注解的重要性 Seam作为一款功能强大的企业级应用开发框架,其核心理念在于提供一种高度集成化的开发方式,旨在简化复杂的业务逻辑处理流程,使开发者能够更加专注于业务逻辑本身而非框架...

    seam+hibernate注册例子

    Seam是一个全面的、集成的Java EE框架,主要用于简化企业级应用的开发,而Hibernate则是一个强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库。在这个"seam+hibernate注册例子"中,我们将探讨...

    Seam Framework 2.0 Reference中文版

    JBoss Seam 是一款基于 Java 的企业级应用开发框架,它简化了应用程序的开发过程,特别是那些涉及复杂的用户交互、业务逻辑以及数据处理的应用。Seam 结合了 JavaServer Faces (JSF)、Java Persistence API (JPA)、...

    jboss Seam2.0 语境相关的组件文档

    JBoss Seam 2.0 是一个开源的Java EE框架,它将企业级服务与富互联网应用(RIA)开发紧密结合,简化了构建复杂Web应用的过程。Seam的核心特性之一是其对上下文(Contexts)和依赖注入(CDI)的支持,这使得开发者...

    Seam - 语境相关的组件

    Seam是一种Java EE框架,它在开发企业级应用程序时提供了高度集成和语境相关的组件模型。这个框架的主要目标是简化复杂性,使开发者能够更高效地构建动态、响应式的Web应用。Seam的核心理念是将不同的技术,如Java...

    seam一些基本功能的实现方法

    Seam是一个Java EE框架,它将企业级服务与富客户端应用程序无缝集成,简化了开发过程。这个框架的主要目标是提供一种灵活、可扩展且易于使用的工具集,使得开发者能够更高效地构建动态Web应用。在“seam一些基本功能...

    Seam2.0学习文档

    Seam 2.0 是一个全面的Java EE框架,它为开发富互联网应用程序(RIA)提供了强大的工具和支持。这个框架整合了多种技术,如JSF、EJB、CDI、Hibernate等,使得开发者能够更轻松地处理上下文、会话管理、组件以及企业...

Global site tag (gtag.js) - Google Analytics