页面安全需要应用程序使用一个pages.xml
文件,而且它也是非常容易配置的。仅仅是简单在你需要保护的page
元素之内包含一个<restrict/>
元素即可。如果restrict
元素没有显式的指定一个限制,那么当通过non-faces(GET)请求访问页面时,将检查隐含的权限/viewId.xhtml:render
,并且任何源于页面的JSF postback(表单提交)都需要权限/viewId.xhtml:restore
。否则,指定的限制将被评定为一个标准的安全表达式,这里有两个例子:
< restrict />
</ page >
这个页面对于non-faces请求隐含一个权限许可:/settings.xhtml:render
,对于faces请求隐含一个权限许可:/settings.xhtml:restore
。
< restrict > #{s:hasRole('admin')} </ restrict >
</ page >
访问这个页面的faces和non-faces请求都需要用户是admin
角色的成员之一。
Seam安全也使得为实体的读取,插入,更新和删除动作应用安全限制成为可能。
为了保护实体类的所有的动作,需要在类本身添加一个@Restrict
注释:
@Name( " customer " )
@Restrict
public class Customer {
![](https://www.cnblogs.com/Images/dot.gif)
}
如果在@Restrict
注释中没有指定表达式,那么执行的默认的安全检查是entity:action
的权限检查,这个权限目标是实体实例,并且这个action
是读取(read)
, 插入(insert)
, 更新(update)
或者删除(delete)
。
也可能通过把@Restrict注解放在相关的实体生命周期的方法上(注解如下所述),而只限制某些动作:
@PostLoad
- 在实体实例从数据库中加载之后调用。用这个方法配置一个read
许可。@PrePersist
- 在插入实体的一个新实例之前调用。用这个方法配置一个insert
许可。@PreUpdate
- 在实体更新之前调用。用这个方法配置一个update
许可。@PreRemove
- 在实体删除之前调用。用这个方法配置一个delete
许可。
这里有一个例子,说明实体方法如何配置成给任何 insert
操作执行安全检查。 请注意这个方法不需要做任何事情,有关安全的唯一重要的是它如何被注解:
public void prePersist() {}
使用 /META-INF/orm.xml
你也可以在/META-INF/orm.xml
中指定一个回调方法:
< 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例子)的实体权限规则的例子。这个被安全检查的实体自动插入到工作内存中(本例中是MemberBlog
):
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提供者。
使用一个EntityListener
来进行EJB3实体Bean的安全检查。你可以使用下面的META-INF/orm.xml
文件安装这个监听器:
< 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 >
SessionFactory
,并且使用了注释,或者orm.xml
文件,那么你不需要做任何其他特别的操作就可以使用实体安全。 Seam提供了一些可以作为@Restrict
的替换的注释,这些注释提供在编译时是安全的好处,因为它们不像@Restrict
那样支持任意的EL表达式。
开箱即用,Seam有着标准的基于CRUD权限的注释,而且添加你自己的注释也只是一个简单的问题。接下来的这些注释是org.jboss.seam.annotations.security
包提供的:
@Insert
@Read
@Update
@Delete
要使用这些注释,你只需简单的把它们放在你希望执行安全检查的方法和参数那里。如果放在方法上,那么它们应该指定一个将检查权限的目标类。如下述例子:
public void createCustomer() {
![](https://www.cnblogs.com/Images/dot.gif)
}
在这个例子中,权限检查将被执行以确保用户有创建一个新的Customer
对象的权利。权限检查的目标是Customer.class
(实际是java.lang.Class
实例本身),并且动作是注释名称的小写值,本例中是insert
。
也可以相同的方式对组件方法的参数进行注释。如果这样注释了,那么它不须要指定一个权限目标(参数值本身就是权限检查的目标):
![](https://www.cnblogs.com/Images/dot.gif)
}
为了创建你自己的安全注释,你只要简单的使用@PermissionCheck
注释,例如:
@Documented
@Retention(RUNTIME)
@Inherited
@PermissionCheck
public @ interface Promote {
Class value() default void . class ;
}
如果你希望使用其他值来重载默认的权限动作名称(小写的注释名称),你应该在@PermissionCheck
注释中指定:
除了支持类型安全的权限注释,Seam安全也提供类型安全的角色注释,这些注释允许你基于当前以验证用户的角色关系来限制访问组件方法。Seam提供开箱即用的这样一个注释,org.jboss.seam.annotations.security.Admin
,它用来限制必须是admin
成员之一的用户才能访问一个方法。为了创建你自己的角色注释,简单的使用org.jboss.seam.annotations.security.RoleCheck
元注释,像下面的例子那样:
@Documented
@Retention(RUNTIME)
@Inherited
@RoleCheck
public @ interface User {
}
@User
注释的方法将被自动拦截并且检查用户是否是相应的角色名称的关系(小写的注释名,本例中是user
)。