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

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

5. 保护实体

    Seam安全也使得为实体的读取,插入,更新和删除动作应用安全限制成为可能。

    为了保护实体类的所有的动作,需要在类本身添加一个@Restrict注释:

    @Entity

    @Name("customer")

    @Restrict

    public class Customer {

    }

    如果在@Restrict注释中没有指定表达式,那么执行的默认的安全检查是entity:action的权限检查,这个权限目标是实体实例,并且这个action是读取(read), 插入(insert), 更新(update)或者删除(delete)。

    也可能通过把@Restrict注解放在相关的实体生命周期的方法上(注解如下所述),而只限制某些动作:

    @PostLoad - 在实体实例从数据库中加载之后调用。用这个方法配置一个 read 许可。

    @PrePersist - 在插入实体的一个新实例之前调用。用这个方法配置一个 insert 许可。

    @PreUpdate - 在实体更新之前调用。用这个方法配置一个 update 许可。

    @PreRemove - 在实体删除之前调用。用这个方法配置一个 delete 许可。

    这里有一个例子,说明实体方法如何配置成给任何 insert 操作执行安全检查。 请注意这个方法不需要做任何事情,有关安全的唯一重要的是它如何被注解:

    @PrePersist @Restrict

    public void prePersist() {}

    使用 /META-INF/orm.xml

    你也可以在/META-INF/orm.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/ormhttp://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例子)的实体权限规则的例子。这个被安全检查的实体自动插入到工作内存中(本例中是MemberBlog):

    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对象的实例,并且分配这个变量名称为principal。变量绑定允许它的值在其他地方可以引用到,比如接下来的一行中比较成员的用户名和Principal的名字。更多详细情况,请参考JBoss Rules文档。

    最后,我们需要安装一个监听器,以集成Seam安全和你的JPA提供者。

    5.1. 使用JPA的实体安全

    使用一个EntityListener来进行EJB3实体Bean的安全检查。你可以使用下面的META-INF/orm.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/ormhttp://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>

    5.2. 使用一个可管理的Hibernate回话的实体安全

    如果你使用一个通过Seam配置的Hibernate的SessionFactory,并且使用了注释,或者orm.xml文件,那么你不需要做任何其他特别的操作就可以使用实体安全。

6. 类型安全的权限注释

    Seam提供了一些可以作为@Restrict的替换的注释,这些注释提供在编译时是安全的好处,因为它们不像@Restrict那样支持任意的EL表达式。

    开箱即用,Seam有着标准的基于CRUD权限的注释,而且添加你自己的注释也只是一个简单的问题。接下来的这些注释是org.jboss.seam.annotations.security包提供的:

    @Insert

    @Read

    @Update

    @Delete

    要使用这些注释,你只需简单的把它们放在你希望执行安全检查的方法和参数那里。如果放在方法上,那么它们应该指定一个将检查权限的目标类。如下述例子:

    @Insert(Customer.class)

    public void createCustomer() {

    }

    在这个例子中,权限检查将被执行以确保用户有创建一个新的Customer对象的权利。权限检查的目标是Customer.class(实际是java.lang.Class实例本身),并且动作是注释名称的小写值,本例中是insert。

    也可以相同的方式对组件方法的参数进行注释。如果这样注释了,那么它不须要指定一个权限目标(参数值本身就是权限检查的目标):

    public void updateCustomer(@Update Customer customer) {

    }

    为了创建你自己的安全注释,你只要简单的使用@PermissionCheck注释,例如:

    @Target({METHOD, PARAMETER})

    @Documented

    @Retention(RUNTIME)

    @Inherited

    @PermissionCheck

    public @interface Promote {

    Class value() default void.class;

    }

    如果你希望使用其他值来重载默认的权限动作名称(小写的注释名称),你应该在@PermissionCheck注释中指定:

    @PermissionCheck("upgrade")

    7. 类型安全的角色注释

    除了支持类型安全的权限注释,Seam安全也提供类型安全的角色注释,这些注释允许你基于当前以验证用户的角色关系来限制访问组件方法。Seam提供开箱即用的这样一个注释,org.jboss.seam.annotations.security.Admin,它用来限制必须是admin成员之一的用户才能访问一个方法。为了创建你自己的角色注释,简单的使用org.jboss.seam.annotations.security.RoleCheck元注释,像下面的例子那样:

    @Target({METHOD})

    @Documented

    @Retention(RUNTIME)

    @Inherited

    @RoleCheck

    public @interface User {

    }

    任何使用了上述例子中的@User注释的方法将被自动拦截并且检查用户是否是相应的角色名称的关系(小写的注释名,本例中是user)。



原创粉丝点击