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

15.6.5. 实体安全控制(Securing Entities)Seam安全模块允许给实体添加read,insert,update和delete操作。如果想要控制所有操作,那么只要在实体类上添加一个@Restrict注解:
Java代码

@Entity 
@Name("customer")  
@Restrict 
public class Customer {  
  ...  

@Entity@Name("customer")@Restrictpublic class Customer {  ...}
如果@Restrict注解内部没有写任何权限判断表达式,那么默认的权限为entity:action,这里的entity为实体的实例。冒号后的操作有四种,分别是:read、insert、update、delete。
也可以单独指定某个生命周期操作,在@Restrict注解之外添加相应的注解到对应生命周期的方法上即可。共有以下四种注解:
- @PostLoad - 当一个实体的实例从数据库中读取出来以后调用。使用这个方法来配置read权限。
- @PrePersist - 插入数据库之前,insert
- @PreUpdate - 更新之前,update
- @PreRemove - 删除之前,delete
下面这个例子介绍了如果给所有insert操作添加安全检查。请注意,这个方法并不需要做任何事情,唯一需要注意的就是,这个方法是如何被声明的:
Java代码

@PrePersist @Restrict 
public void prePersist() {} 
@PrePersist @Restrictpublic void prePersist() {}
你也可以在/META-INF/orm.xml文件中定义:
Xml代码

<?xml version="1.0" encoding="UTF-8"?> 
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" 
                 version="1.0"> 
 
   <entity class="Customer"> 
      <pre-persist method-name="prePersist" /> 
   </entity> 
 
</entity-mappings> 
<?xml version="1.0" encoding="UTF-8"?><entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"                 version="1.0">   <entity class="Customer">      <pre-persist method-name="prePersist" />   </entity></entity-mappings>
当然,你仍然需要使用@Restrict来注解Customer对象中的prePersist()方法。
下面这个例子介绍了使用规则判断当前用户是否有权限添加一篇新的MemberBlog记录(来自seamspace示例)。
在下面这个规则中,需要被检查权限的实体会被自动插入到working memory中(这里就是指MemberBlog对象的实例):
Xml代码

rule InsertMemberBlog  
  no-loop  
  activation-group "permissions"  
when  
  principal: Principal()  
  memberBlog: MemberBlog(member : member -> (member.getUsername().equals(principal.getName())))  
  check: PermissionCheck(target == memberBlog, action == "insert", granted == false)  
then  
  check.grant();  
end; 
rule InsertMemberBlog  no-loop  activation-group "permissions"when  principal: Principal()  memberBlog: MemberBlog(member : member -> (member.getUsername().equals(principal.getName())))  check: PermissionCheck(target == memberBlog, action == "insert", granted == false)then  check.grant();end;
这条规则的含义是:如果当前被验证用户(在规则中是用Principal来表示的)的姓名与当前将要被创建的blog的用户名相同,则检查当前用户是否拥有memberBlog:insert权限(还是当姓名相同的时候授予当前用户插入权限,译者并不是很清楚)。
类似“principal: Principal()”的结构代表一个变量绑定,它将Principal对象的实例从working memory中取出(在authentication的时候装载进入working memory的),并且给他取个变量名叫principal。变量一旦被绑定以后,其他地方就可以通过变量名来获取对象,例如在接下来的几行中,将member的用户名与Principal的name比较。如果想要了解更多有关规则的内容,请参考Drools文档。
最后,我们需要添加一个监听器来将seam security与你的JPA provider集成起来。
15.6.5.1. 使用JPA实现实体安全控制(Entity security with JPA)EJB3实体的安全控制通过一个EntityListener来实现。你可以在META-INF/orm.xml写以下代码来安装这个监听器:
Xml代码

<?xml version="1.0" encoding="UTF-8"?> 
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" 
                 version="1.0"> 
 
    <persistence-unit-metadata> 
        <persistence-unit-defaults> 
            <entity-listeners> 
                <entity-listener class="org.jboss.seam.security.EntitySecurityListener"/> 
            </entity-listeners> 
        </persistence-unit-defaults> 
    </persistence-unit-metadata> 
 
</entity-mappings> 
<?xml version="1.0" encoding="UTF-8"?><entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"                 version="1.0">    <persistence-unit-metadata>        <persistence-unit-defaults>            <entity-listeners>                <entity-listener class="org.jboss.seam.security.EntitySecurityListener"/>            </entity-listeners>        </persistence-unit-defaults>    </persistence-unit-metadata></entity-mappings>
15.6.5.2. 使用一个受管的Hibernate Session来实现实体安全控制(Entity security with a Managed Hibernate Session) 如果你在Seam中使用Hibernate的SessionFactory,并且也使用了注解或者orm.xml文件进行映射配置,那么你不需要做任何事情就可以使用实体安全控制。
15.6.6. 类型安全的权限注解(Typesafe Permission Annotations)seam提供了一组用来替代@Restrict的安全注解。由于这些注解不能想@Restrict这样灵活,所以这些注解提供了更高级别的编译时安全(compile-time safety)控制。
seam提供了一组标准的CRUD注解,当然,你可以扩展并添加属于你自己的注解。下面几个注解你能够在org.jboss.seam.annotations.security包内找到:
- @Insert
- @Read
- @Update
- @Delete
只需要将它们写在你想要检查权限的方法或者参数前面即可。如果放在方法前面,那么你需要指定一下需要检查权限的目标的class:
Java代码

@Insert(Customer.class)  
public void createCustomer() {  
    ...  

@Insert(Customer.class)public void createCustomer() {    ...}
在这个例子里面,当用户尝试创建一个新的Customer对象的时候,会去检查用户是否有相应权限。需要检查权限的对象为Customer.class(实际上是其本身的java.lang.Class实例),而需要判断权限的操作为注解的小写方式,这里为insert。
这种注解同样也可以用在方法的参数上面。如果加在参数上,那么你不需要指定权限验证的目标(因为参数值本身就将作为权限验证的目标):
Java代码

public void updateCustomer(@Update Customer customer) {  
    ...  

public void updateCustomer(@Update Customer customer) {    ...}
如果你想要编写自己的权限验证注解接口,只需要在注解接口上添加@PermissionCheck即可,例如:
Java代码

@Target({METHOD, PARAMETER})  
@Documented 
@Retention(RUNTIME)  
@Inherited 
@PermissionCheck 
public @interface Promote {  
   Class value() default void.class;  

@Target({METHOD, PARAMETER})@Documented@Retention(RUNTIME)@Inherited@PermissionCheckpublic @interface Promote {   Class value() default void.class;}
如果你想覆盖默认的权限判断操作,那么你可以在@PermissionCheck中指定你想覆盖的操作名称(小写):
Java代码

@PermissionCheck("upgrade") 
@PermissionCheck("upgrade")
15.6.7. 类型安全的角色控制注解(Typesafe Role Annotations)除了权限注解之外,Seam安全模块同样也提供了类型安全的角色注解。这些注解允许你根据用户所拥有的角色来判断是否能够进行相关操作。
Seam单独提供了这么一个注解:org.jboss.seam.annotations.security.Admin。这个注解用来判断用户是否拥有admin角色(只要你的程序里面支持这个角色)。想要创建你自己的角色判断注解,只需要在你编写的注解接口上额外添加一个org.jboss.seam.annotations.security.RoleCheck注解,例如:
Java代码

@Target({METHOD})  
@Documented 
@Retention(RUNTIME)  
@Inherited 
@RoleCheck 
public @interface User {   

@Target({METHOD})@Documented@Retention(RUNTIME)@Inherited@RoleCheckpublic @interface User { }
当编写了上面这个注解以后,只要添加了这个注解的地方,就会自动去检查用户是否拥有user角色(注解名称的小写形式)。

你可能感兴趣的:(Hibernate,jboss,jpa,Security,seam)