- 浏览: 1053240 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (279)
- Apache net (10)
- JBoss Rules (3)
- Seam ACL (1)
- Seam (14)
- Seam JPA高级权限验证 (8)
- 待解决的问题.... (1)
- JAVA (43)
- Dwr (4)
- Ajax4JSF (1)
- JavaScript (27)
- 生活小常识 (17)
- Richfaces (3)
- seam自己经历 (14)
- JDBC (1)
- mysql (6)
- WebService (10)
- Java Web (4)
- Hibernate (13)
- J2EE框架整合 (3)
- Spring (9)
- BEA Weblogic (1)
- XML (1)
- log4j (6)
- CSS (2)
- javaIO文件的读写 (5)
- SVN服务器的安装 (5)
- powerDesigner (2)
- SQL常用语句 (3)
- wicket初学 (5)
- eclipse (7)
- 正则表达式 (1)
- ExtJS (6)
- maven(m2eclipse) (1)
- struts2.0 (9)
- JPA (6)
- struts2.0整合spring2.5 (9)
- linux (6)
- Oracle (5)
- Servlet (3)
- MyEclipseGen (0)
最新评论
-
qq_31247573:
JAVA 获取http返回XML的数据 -
jasmine_20100810:
...
linux下tomcat服务的启动、关闭与错误跟踪 -
weiaiFang0624:
视频下载地址:http://download.csdn.net ...
there is no action mapped for namespace / and action name解决办法 -
p476462534:
JS控制表单form的提交 -
dandongsoft:
aaaaaaaaaaaaaaa
httpClient,JAVA访问http request response
Permission Management
尽管 Identity Management 提供了一致的API来管理用户帐户,我们依然需要一个方式来管理用户许可(Permission)。从前一个版本以来,在Seam 2.1.0中的验证特性经过了整个的修订。在以前开发者需要继承一个内建的 Identity 组件来实现自定义的许可(Permission)检查,在Seam 2.1.0中提供了一个可插拔的系统,可以让你注册你自己的许可(Permission)分析器而不用继承其他的组件了。下图展示了这些东西是如何协作的:
在上图中, Identity 现在使用 PermissionMapper 映射一个特别的ResolverChain来执行许可(Permission)检查,该ResolverChain可以配置一个或多个PermissionResolvers。Seam提供了 RuleBasedPermissionResolver (for resolving rule-based permission checks) 和 PersistentPermissionResolver (for performing checks based on permissions stored in persistent storage, such as a database)。如果你的程序需要自定义安全管理,实现你自己的PermissionResolver 也是相当简单的。
我想在进一步前进之前,我们需要定义下许可(Permission)是什么。在Seam中,许可(Permission)有3个方面:
* A target, 一个在某些方面起作用的对象
* An action, 在 target 上被执行的动作
* A recipient, 具有在target上执行特定action的许可(Permission)的用户或则角色实体
许可(Permission)检查的target就是PermissionMapper用来判断使用那个ResolverChain来执行检查。这样可以实现为不同的对象配置不同的PermissionResolvers。例如:你可能希望仅仅使用RuleBasedPermissionResolver来执行Customer对象的许可(Permission)检查,同时使用PersistentPermissionResolver来执行Invoice对象上的许可(Permission)检查。PermissionMapper支持这种灵活性。
让我们实际的看看这些应用。
Persistent Permissions
SeamSpace示例允许用户上传一个图片。其他用户在浏览用户信息的时候可以看到该图片:
现在我们假设一些图片你想设置为私有的,而其他一些图片你想仅仅显示给你的朋友。点击你图片下的 padlock 图标,会打开图片的许可(Permission)管理页面:
在这个页面,我们可以看到那些用户和角色有查看这个图片的许可。在这个示例中,仅仅我的朋友具有查看该图片的权限。现在我想让该站点的任何用户都可以看到该图片。可以点击'new permission'来授权,会打开许可详细信息页面:
在这里我们通过选择角色或则具体的用户来提供特殊的许可权限。我希望所有的用户都可以查看,所以我从角色列表中选择‘user’,然后点击‘view’ checkbox。点击save按钮保存设置,然后返回到许可管理界面,在这里可以看到我设置的新许可:
当我们授予一个新的许可的时候,实际发生了什么呢?我们看看在这个场景后面使用的组件,ImagePermission. 下面是相关的代码:
@Name("imagePermission")
@Scope(CONVERSATION)
public class ImagePermission implements Serializable
{
// (snip)
@In PermissionManager permissionManager;
@In PermissionSearch permissionSearch;
private MemberImage target;
private Principal recipient;
@SuppressWarnings("unchecked")
@Begin(nested = true)
public void createPermission() {
target = (MemberImage) permissionSearch.getTarget();
// (snip)
}
public void applyPermissions() {
// (snip)
List<Permission> permissions = new ArrayList<Permission>();
for (String role : selectedRoles)
{
Principal r = new Role(role);
for (String action : selectedActions)
{
permissions.add(new Permission(target, action, r));
}
}
for (Member friend : selectedFriends)
{
MemberAccount acct = (MemberAccount) entityManager.createQuery(
"select a from MemberAccount a where a.member = :member")
.setParameter("member", friend)
.getSingleResult();
Principal p = new SimplePrincipal(acct.getUsername());
for (String action : selectedActions)
{
permissions.add(new Permission(target, action, p));
}
}
permissionManager.grantPermissions(permissions);
Conversation.instance().endBeforeRedirect();
}
// (snip)
}
从上面的代码中我们可以看到 ImagePermission 是一个会话作用域(conversation-scoped)的组件。其实,它的功能被实现为一个嵌套的作用域,在同一个target对象上可以同时打开多个 'new permission' 窗口来操作。我们还可以看到PermissionManager通过@In 注解注入进来了。
现在 createPermission() 方法开始一个嵌套的会话 (thanks to the @Begin(nested = true) annotation),然后在我们的target对象中保存一个引用。当用户点击save按钮,在分配了指定的许可后,用来构建一些Permission对象来执行授权的applyPermissions()方法被调用了。在该函数内,使用一些授权的许可来调用PermissionManager.grant()。我们发些时间来详细解释下这个 PermissionManager (the heart of the Permission Management API)。
The PermissionManager Component
就像 IdentityManager 用来处理用户和角色操作一样,PermissionManager 被设计为来操作许可。它提供了API来允许授权和激活许可,或则一个target对象的列表。我们来看看一些方法:
* listPermissions(String target, String action)
* listPermissions(Object target)
* grantPermission(Permission permission)
* grantPermissions(List<Permission> permissions)
* revokePermission(Permission permission)
* revokePermissions(List<Permission> permissions)
就像 IdentityManager 需要一个 IdentityStore 来保存数据, PermissionManager 也需要一个 PermissionStore 来和持久化存储打交到。Seam 只提供了一个 PermissionStore 实现 - JpaPermissionStore, 可以通过JPA来和数据库存在互操作。在理论上也可以把许可信息保存在LDAP目录中,或则一个普通文件中,但是大多数情况下还是保存在一个数据库中的。
现在来看看SeamSapce示例中 AccountPermission entity bean的代码,下面的代码为了排版被截断了:
@Entity
public class AccountPermission implements Serializable
{
// snip field declarations, etc
@PermissionUser @PermissionRole
public String getRecipient() { return recipient; }
public void setRecipient(String recipient) { this.recipient = recipient; }
@PermissionTarget public String getTarget() { return target; }
public void setTarget(String target) { this.target = target; }
@PermissionAction
public String getAction() { return action; }
public void setAction(String action) { this.action = action; }
@PermissionDiscriminator
public String getDiscriminator() { return discriminator; }
public void setDiscriminator(String discriminator) { this.discriminator = discriminator; }
}
再一次的,我们注意到使用了一些特殊的注解。这里我告诉你,许可既可以指定到用户上也可以指定到角色上。这就意味着可以把许可信息保存的分开的表格中,这从性能角度来说,把他们保存在单个表中,使用一个辨别器列(discriminator column)来区分他们,可能看起来更合适。因此在上面的代码中,我们看到getDiscriminator() 使用了@PermissionDiscriminator注解,表明该列用来判断许可是应用到用户上还是角色上。
继续向下看,用来配置一个保存许可信息的实体注解如下:
* @PermissionUser - designates the field that contains the name of the recipient of the permission (for user-assigned permissions)
* @PermissionRole - same as above, but for role-assigned permissions
* @PermissionTarget - contains a unique identifier string, identifying a single instance of an object. Alternatively, can contain a class name or any arbitrary string for the designation of more generalised permissions.
* @PermissionAction - contains a list of the actions that the recipient may perform on the target object.
* @PermissionDiscriminator - see paragraph above
这里说明下 - permission management 特性只用来管理持久的许可信息( persistent permissions)。当然在大多数情况下,你可能希望通过业务逻辑来应用许可权限,例如:用户应该具有查看和管理他们自己图片的权限。这类许可有Seam的rule-based security(基于角色的安全)来处理,在下面我们来详细讨论下这个问题。
Rule-based Permissions
Seam 基于Drools 提供了一个rule-based security模型,因此这并不是一个真正的新功能。我们这里来重新温习下这是如何应用到我们的示例项目SeamSpace中的。
继续图片安全这个话题,当处理用户图片的时候,除了我们上面讨论的问题外,显然我们需要一些基础的安全规则。在默认的情况下,查看用户的图片被安全规则限制了,这意味着在SeamSpace中,如果你想看一个用户的图片,你必须在被该用户授权后才可以查看(either via a persistent permission grant, or a security rule)。另外请记住,我们特别的需要允许下面的一些事情:
* Users should be allowed to grant and revoke permissions for their own images
* Users should be allowed to delete their own images
* User profile images (a user's main image, i.e. their 'avatar') should always be viewable by anyone
* Users should always be allowed to view their own images (of course)
* User images with 'friend' permissions should be viewable by the user's friends (more on this in a bit)
现在我们详细的看看这些规则。首先,用户应该允许给他们的图片授予和撤回许可权限。这是相当直接的,并且作为两个独立的规则实现了。当和对象许可一起使用的时候,Seam会插入一个PermissionCheck对象到Drools的工作内存(working memory)中,该内存包含许可目标和根据用户要做什么分别由'seam.grant-permission' 或则 'seam.revoke-permission'(based on whether PermissionManager.grantPermission() or PermissionManager.revokePermission() is called)定义的一个动作(containing both the target of the permission, and an action either being 'seam.grant-permission' or 'seam.revoke-permission' depending on what the user is trying to do (based on whether PermissionManager.grantPermission() or PermissionManager.revokePermission() is called))。用于验证用户的MemberAccount示例一直在working memory中,在实际上下面的规则是: '如果我们正在处理的MemberImage是属于当前登陆的用户的,那么就授予许可权限(if the MemberImage for which we're performing the permission check is owned by the current user, then grant the permission)':
rule GrantImagePermissions
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "seam.grant-permission", granted == false)
then
check.grant();
end
rule RevokeImagePermissions
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "seam.revoke-permission", granted == false)
then
check.grant();
end
在下一步,我们也需要一个允许用户删除他们自己图片的规则。和第一个规则相似,我们验证当前执行删除的图片是否属性该用户的,如果是那么就授予权限:
rule DeleteImage
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "delete", granted == false)
then
check.grant();
end
用于查看用户图片的规则有点不同。这里我们简单的测试 -- 正在查看的图片是用户自己的图片(Here we simply test that the image being viewed is the profile image for the owning member) (i.e. image.getMember().getPicture() == image):
rule ViewProfileImage
no-loop
activation-group "permissions"
when
image: MemberImage()
check: PermissionCheck(target == image, action == "view", granted == false)
eval( image.getMember().getPicture() == image )
then
check.grant();
end
还有,用户应该总是可以查看他们自己的图片。这个权限验证类似于第一个规则,在那里我们简单的验证图片的所有者是否为当前登陆的用户:
rule ViewMyImages
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "view")
then
check.grant();
end
Conditional Roles
最后,为了当我们的朋友查看我们的图片,我们需要定义一个特殊的规则。在前面我们看到了如何给‘friends’角色授权,然而根据上下文的不同‘riend’可能具有不同的意思。可以认为,在系统中的任何一个用户都是某人的‘friend’,你们当其他人来看图片的时候我们如何定义他们是否是一个‘friend’呢?这就是条件角色(conditional roles )的领域了,这些角色是特殊的,并且不能直接的授予给用户。
当一个对象的权限检查通过安全(security)API检查过后, permission manager就通知 security API一个conditional role被授予权限了,需要执行一个特殊的基础规则(rule-based)来验证该用户是否具有该角色,但在仅仅在permission check的上下文中执行。要实现这个功能,和往常一样把一个PermissionCheck对象插入到包含target和action的working memory中,然而也会附加的插入一个RoleCheck对象,该对象包含用来对比的conditional role的名字。这样我们可以写一个安全规则来验证是否授予conditional role权限:
rule FriendViewImage
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.isFriend(acct.member)))
PermissionCheck(target == image, action == "view")
role: RoleCheck(name == "friends")
then
role.grant();
end
这个规则检查当前验证的用户是否在图片所有者的朋友列表中。如果在的话,角色就暂时的授予这个许可检查。在某些复杂安全规则的情况下这具有非常大的灵活性( This allows great flexibility in assigning complex security rules to dynamic groups of users (in this case, a user's friends list) that don't necessarily warrant having their own role/group, due to either impracticality or design restrictions).
Strongly-typed Security Annotations
最后,作为结束我们来看看一些新的安全注解。为了使Seam Security看起来更'Web Beansy',我们引入了一些用于现在组件方法的类型安全的注解。通过使用meta-annotations,我们可以提供一些安全注解来应用安全限制到函数上或则参数上。Seam提供了一些开箱即用的注解,他们是标准的CRUD注解 (@Insert, @Read, @Update, @Delete) ,并且添加你自己的注解也是非常简单的。看看下面的例子:
@Begin @Insert(Customer.class)
public void createCustomer() {
这个注解的功能是,除非你具有插入新customer对象的权利,放置你不能调用createCustomer方法。类似的,我们可以注解一个方法的参数:
public void updateCustomer(@Update Customer customer) {
创建自己的注解只需要使用@PermissionCheck就可以了。来看个示例,你希望创建一个新的‘Promote’许可。该注解可以非常简单的实现,如下:
@Target({METHOD, PARAMETER})
@Documented
@Retention(RUNTIME)
@Inherited
@PermissionCheck
public @interface Promote {
Class value() default void.class;
}
定义后,就可以直接使用了:
public void promoteStaff(@Promote Staff person) {
如果写一个基于规则的许可,该规则看起来就像这样:
rule PromoteStaffMember
no-loop
activation-group "permissions"
when
acct: MemberAccount()
Role(name == 'admin')
staff: Staff()
check: PermissionCheck(target == staff, action == "promote")
then
check.grant();
end
许可动作(permission action)变为注解的小些名称了。这真的是很简单的!
同时我们仍然支持遗留的用于基于表达式的安全检查的@Restrict注解,我建议各位都使用新的类型安全的注解,至少在编译期安全检查就提供了简单的验证。
Conclusion
到这里就结束了JBoss Seam中的新安全特性。这里是一些参考的链接:
JBoss Seam Community Site (downloads, documentation, forums) - http://www.seamframework.org/
JBoss Seam 中文社区站点(下载,文档,论坛) - http://www.seamframework.cn/
JBoss Home Page - http://www.jboss.org
尽管 Identity Management 提供了一致的API来管理用户帐户,我们依然需要一个方式来管理用户许可(Permission)。从前一个版本以来,在Seam 2.1.0中的验证特性经过了整个的修订。在以前开发者需要继承一个内建的 Identity 组件来实现自定义的许可(Permission)检查,在Seam 2.1.0中提供了一个可插拔的系统,可以让你注册你自己的许可(Permission)分析器而不用继承其他的组件了。下图展示了这些东西是如何协作的:
在上图中, Identity 现在使用 PermissionMapper 映射一个特别的ResolverChain来执行许可(Permission)检查,该ResolverChain可以配置一个或多个PermissionResolvers。Seam提供了 RuleBasedPermissionResolver (for resolving rule-based permission checks) 和 PersistentPermissionResolver (for performing checks based on permissions stored in persistent storage, such as a database)。如果你的程序需要自定义安全管理,实现你自己的PermissionResolver 也是相当简单的。
我想在进一步前进之前,我们需要定义下许可(Permission)是什么。在Seam中,许可(Permission)有3个方面:
* A target, 一个在某些方面起作用的对象
* An action, 在 target 上被执行的动作
* A recipient, 具有在target上执行特定action的许可(Permission)的用户或则角色实体
许可(Permission)检查的target就是PermissionMapper用来判断使用那个ResolverChain来执行检查。这样可以实现为不同的对象配置不同的PermissionResolvers。例如:你可能希望仅仅使用RuleBasedPermissionResolver来执行Customer对象的许可(Permission)检查,同时使用PersistentPermissionResolver来执行Invoice对象上的许可(Permission)检查。PermissionMapper支持这种灵活性。
让我们实际的看看这些应用。
Persistent Permissions
SeamSpace示例允许用户上传一个图片。其他用户在浏览用户信息的时候可以看到该图片:
现在我们假设一些图片你想设置为私有的,而其他一些图片你想仅仅显示给你的朋友。点击你图片下的 padlock 图标,会打开图片的许可(Permission)管理页面:
在这个页面,我们可以看到那些用户和角色有查看这个图片的许可。在这个示例中,仅仅我的朋友具有查看该图片的权限。现在我想让该站点的任何用户都可以看到该图片。可以点击'new permission'来授权,会打开许可详细信息页面:
在这里我们通过选择角色或则具体的用户来提供特殊的许可权限。我希望所有的用户都可以查看,所以我从角色列表中选择‘user’,然后点击‘view’ checkbox。点击save按钮保存设置,然后返回到许可管理界面,在这里可以看到我设置的新许可:
当我们授予一个新的许可的时候,实际发生了什么呢?我们看看在这个场景后面使用的组件,ImagePermission. 下面是相关的代码:
@Name("imagePermission")
@Scope(CONVERSATION)
public class ImagePermission implements Serializable
{
// (snip)
@In PermissionManager permissionManager;
@In PermissionSearch permissionSearch;
private MemberImage target;
private Principal recipient;
@SuppressWarnings("unchecked")
@Begin(nested = true)
public void createPermission() {
target = (MemberImage) permissionSearch.getTarget();
// (snip)
}
public void applyPermissions() {
// (snip)
List<Permission> permissions = new ArrayList<Permission>();
for (String role : selectedRoles)
{
Principal r = new Role(role);
for (String action : selectedActions)
{
permissions.add(new Permission(target, action, r));
}
}
for (Member friend : selectedFriends)
{
MemberAccount acct = (MemberAccount) entityManager.createQuery(
"select a from MemberAccount a where a.member = :member")
.setParameter("member", friend)
.getSingleResult();
Principal p = new SimplePrincipal(acct.getUsername());
for (String action : selectedActions)
{
permissions.add(new Permission(target, action, p));
}
}
permissionManager.grantPermissions(permissions);
Conversation.instance().endBeforeRedirect();
}
// (snip)
}
从上面的代码中我们可以看到 ImagePermission 是一个会话作用域(conversation-scoped)的组件。其实,它的功能被实现为一个嵌套的作用域,在同一个target对象上可以同时打开多个 'new permission' 窗口来操作。我们还可以看到PermissionManager通过@In 注解注入进来了。
现在 createPermission() 方法开始一个嵌套的会话 (thanks to the @Begin(nested = true) annotation),然后在我们的target对象中保存一个引用。当用户点击save按钮,在分配了指定的许可后,用来构建一些Permission对象来执行授权的applyPermissions()方法被调用了。在该函数内,使用一些授权的许可来调用PermissionManager.grant()。我们发些时间来详细解释下这个 PermissionManager (the heart of the Permission Management API)。
The PermissionManager Component
就像 IdentityManager 用来处理用户和角色操作一样,PermissionManager 被设计为来操作许可。它提供了API来允许授权和激活许可,或则一个target对象的列表。我们来看看一些方法:
* listPermissions(String target, String action)
* listPermissions(Object target)
* grantPermission(Permission permission)
* grantPermissions(List<Permission> permissions)
* revokePermission(Permission permission)
* revokePermissions(List<Permission> permissions)
就像 IdentityManager 需要一个 IdentityStore 来保存数据, PermissionManager 也需要一个 PermissionStore 来和持久化存储打交到。Seam 只提供了一个 PermissionStore 实现 - JpaPermissionStore, 可以通过JPA来和数据库存在互操作。在理论上也可以把许可信息保存在LDAP目录中,或则一个普通文件中,但是大多数情况下还是保存在一个数据库中的。
现在来看看SeamSapce示例中 AccountPermission entity bean的代码,下面的代码为了排版被截断了:
@Entity
public class AccountPermission implements Serializable
{
// snip field declarations, etc
@PermissionUser @PermissionRole
public String getRecipient() { return recipient; }
public void setRecipient(String recipient) { this.recipient = recipient; }
@PermissionTarget public String getTarget() { return target; }
public void setTarget(String target) { this.target = target; }
@PermissionAction
public String getAction() { return action; }
public void setAction(String action) { this.action = action; }
@PermissionDiscriminator
public String getDiscriminator() { return discriminator; }
public void setDiscriminator(String discriminator) { this.discriminator = discriminator; }
}
再一次的,我们注意到使用了一些特殊的注解。这里我告诉你,许可既可以指定到用户上也可以指定到角色上。这就意味着可以把许可信息保存的分开的表格中,这从性能角度来说,把他们保存在单个表中,使用一个辨别器列(discriminator column)来区分他们,可能看起来更合适。因此在上面的代码中,我们看到getDiscriminator() 使用了@PermissionDiscriminator注解,表明该列用来判断许可是应用到用户上还是角色上。
继续向下看,用来配置一个保存许可信息的实体注解如下:
* @PermissionUser - designates the field that contains the name of the recipient of the permission (for user-assigned permissions)
* @PermissionRole - same as above, but for role-assigned permissions
* @PermissionTarget - contains a unique identifier string, identifying a single instance of an object. Alternatively, can contain a class name or any arbitrary string for the designation of more generalised permissions.
* @PermissionAction - contains a list of the actions that the recipient may perform on the target object.
* @PermissionDiscriminator - see paragraph above
这里说明下 - permission management 特性只用来管理持久的许可信息( persistent permissions)。当然在大多数情况下,你可能希望通过业务逻辑来应用许可权限,例如:用户应该具有查看和管理他们自己图片的权限。这类许可有Seam的rule-based security(基于角色的安全)来处理,在下面我们来详细讨论下这个问题。
Rule-based Permissions
Seam 基于Drools 提供了一个rule-based security模型,因此这并不是一个真正的新功能。我们这里来重新温习下这是如何应用到我们的示例项目SeamSpace中的。
继续图片安全这个话题,当处理用户图片的时候,除了我们上面讨论的问题外,显然我们需要一些基础的安全规则。在默认的情况下,查看用户的图片被安全规则限制了,这意味着在SeamSpace中,如果你想看一个用户的图片,你必须在被该用户授权后才可以查看(either via a persistent permission grant, or a security rule)。另外请记住,我们特别的需要允许下面的一些事情:
* Users should be allowed to grant and revoke permissions for their own images
* Users should be allowed to delete their own images
* User profile images (a user's main image, i.e. their 'avatar') should always be viewable by anyone
* Users should always be allowed to view their own images (of course)
* User images with 'friend' permissions should be viewable by the user's friends (more on this in a bit)
现在我们详细的看看这些规则。首先,用户应该允许给他们的图片授予和撤回许可权限。这是相当直接的,并且作为两个独立的规则实现了。当和对象许可一起使用的时候,Seam会插入一个PermissionCheck对象到Drools的工作内存(working memory)中,该内存包含许可目标和根据用户要做什么分别由'seam.grant-permission' 或则 'seam.revoke-permission'(based on whether PermissionManager.grantPermission() or PermissionManager.revokePermission() is called)定义的一个动作(containing both the target of the permission, and an action either being 'seam.grant-permission' or 'seam.revoke-permission' depending on what the user is trying to do (based on whether PermissionManager.grantPermission() or PermissionManager.revokePermission() is called))。用于验证用户的MemberAccount示例一直在working memory中,在实际上下面的规则是: '如果我们正在处理的MemberImage是属于当前登陆的用户的,那么就授予许可权限(if the MemberImage for which we're performing the permission check is owned by the current user, then grant the permission)':
rule GrantImagePermissions
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "seam.grant-permission", granted == false)
then
check.grant();
end
rule RevokeImagePermissions
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "seam.revoke-permission", granted == false)
then
check.grant();
end
在下一步,我们也需要一个允许用户删除他们自己图片的规则。和第一个规则相似,我们验证当前执行删除的图片是否属性该用户的,如果是那么就授予权限:
rule DeleteImage
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "delete", granted == false)
then
check.grant();
end
用于查看用户图片的规则有点不同。这里我们简单的测试 -- 正在查看的图片是用户自己的图片(Here we simply test that the image being viewed is the profile image for the owning member) (i.e. image.getMember().getPicture() == image):
rule ViewProfileImage
no-loop
activation-group "permissions"
when
image: MemberImage()
check: PermissionCheck(target == image, action == "view", granted == false)
eval( image.getMember().getPicture() == image )
then
check.grant();
end
还有,用户应该总是可以查看他们自己的图片。这个权限验证类似于第一个规则,在那里我们简单的验证图片的所有者是否为当前登陆的用户:
rule ViewMyImages
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.memberId.equals(acct.member.memberId)))
check: PermissionCheck(target == image, action == "view")
then
check.grant();
end
Conditional Roles
最后,为了当我们的朋友查看我们的图片,我们需要定义一个特殊的规则。在前面我们看到了如何给‘friends’角色授权,然而根据上下文的不同‘riend’可能具有不同的意思。可以认为,在系统中的任何一个用户都是某人的‘friend’,你们当其他人来看图片的时候我们如何定义他们是否是一个‘friend’呢?这就是条件角色(conditional roles )的领域了,这些角色是特殊的,并且不能直接的授予给用户。
当一个对象的权限检查通过安全(security)API检查过后, permission manager就通知 security API一个conditional role被授予权限了,需要执行一个特殊的基础规则(rule-based)来验证该用户是否具有该角色,但在仅仅在permission check的上下文中执行。要实现这个功能,和往常一样把一个PermissionCheck对象插入到包含target和action的working memory中,然而也会附加的插入一个RoleCheck对象,该对象包含用来对比的conditional role的名字。这样我们可以写一个安全规则来验证是否授予conditional role权限:
rule FriendViewImage
no-loop
activation-group "permissions"
when
acct: MemberAccount()
image: MemberImage(mbr : member -> (mbr.isFriend(acct.member)))
PermissionCheck(target == image, action == "view")
role: RoleCheck(name == "friends")
then
role.grant();
end
这个规则检查当前验证的用户是否在图片所有者的朋友列表中。如果在的话,角色就暂时的授予这个许可检查。在某些复杂安全规则的情况下这具有非常大的灵活性( This allows great flexibility in assigning complex security rules to dynamic groups of users (in this case, a user's friends list) that don't necessarily warrant having their own role/group, due to either impracticality or design restrictions).
Strongly-typed Security Annotations
最后,作为结束我们来看看一些新的安全注解。为了使Seam Security看起来更'Web Beansy',我们引入了一些用于现在组件方法的类型安全的注解。通过使用meta-annotations,我们可以提供一些安全注解来应用安全限制到函数上或则参数上。Seam提供了一些开箱即用的注解,他们是标准的CRUD注解 (@Insert, @Read, @Update, @Delete) ,并且添加你自己的注解也是非常简单的。看看下面的例子:
@Begin @Insert(Customer.class)
public void createCustomer() {
这个注解的功能是,除非你具有插入新customer对象的权利,放置你不能调用createCustomer方法。类似的,我们可以注解一个方法的参数:
public void updateCustomer(@Update Customer customer) {
创建自己的注解只需要使用@PermissionCheck就可以了。来看个示例,你希望创建一个新的‘Promote’许可。该注解可以非常简单的实现,如下:
@Target({METHOD, PARAMETER})
@Documented
@Retention(RUNTIME)
@Inherited
@PermissionCheck
public @interface Promote {
Class value() default void.class;
}
定义后,就可以直接使用了:
public void promoteStaff(@Promote Staff person) {
如果写一个基于规则的许可,该规则看起来就像这样:
rule PromoteStaffMember
no-loop
activation-group "permissions"
when
acct: MemberAccount()
Role(name == 'admin')
staff: Staff()
check: PermissionCheck(target == staff, action == "promote")
then
check.grant();
end
许可动作(permission action)变为注解的小些名称了。这真的是很简单的!
同时我们仍然支持遗留的用于基于表达式的安全检查的@Restrict注解,我建议各位都使用新的类型安全的注解,至少在编译期安全检查就提供了简单的验证。
Conclusion
到这里就结束了JBoss Seam中的新安全特性。这里是一些参考的链接:
JBoss Seam Community Site (downloads, documentation, forums) - http://www.seamframework.org/
JBoss Seam 中文社区站点(下载,文档,论坛) - http://www.seamframework.cn/
JBoss Home Page - http://www.jboss.org
发表评论
-
JBoss Seam事件机制 (4):页面动作
2009-06-24 13:47 1670在JBoss Seam事件机制(1 ... -
JBoss Seam的事件机制 (3)
2009-06-24 13:46 1405JBoss Seam如何做到松耦合 ... -
JBoss Seam的事件机制 (2)
2009-06-24 13:45 1283JBoss Seam如何做到松耦合 ... -
JBoss Seam的事件机制 (1) 内置的上下文事件
2009-06-24 13:45 1648在JBoss Seam的事件机制(1)概述中我们提到Seam提 ... -
Seam 2.1中的安全升级 (一)
2009-06-24 13:41 1365Seam安全升级 by Shane Bryzak,翻译:JS ... -
seam2.1权限验证(15.5)@Restrict注解 (三)
2009-06-24 13:39 141915.6.8. 权限验证的模型 ... -
seam2.1权限验证(15.5)@Restrict注解 (二)
2009-06-24 13:37 158615.6.5. 实体安全控制(Securing Entitie ... -
seam2.1权限验证(15.5)@Restrict注解 (一)
2009-06-24 13:36 234215.5. 错误消息安全API内 ... -
seam2.1权限验证(15.3) JAAS
2009-06-24 13:35 181615.3. 验证Seam安全中的验证特性是基于JAAS (Ja ... -
seam2.1权限验证(15.4) jpa-identity-store
2009-06-24 13:34 205315.4. 身份管理身份管理功能提供了一组标准的API接口,用 ... -
seam发送邮件email示例
2009-06-24 13:33 1596以下转自csdn上的一个回答,留着用的时候参考,防止到时找不到 ... -
扩展seam组件
2009-06-24 13:31 1095任何一个框架都必须拥有一个非常重要的功能:可扩展性。JBoss ... -
Seam Bean验证快速进阶II:自定义约束
2009-06-24 13:26 1393本文为Bean验证系列的第二部分。总体介绍请阅读这篇文章。本文 ...
相关推荐
在 Seam 2.1 中,最显著的变化之一就是增强了安全性方面的功能,尤其是在用户权限验证机制上。这一版本不仅提供了更为精细的权限控制选项,还增加了对最新安全标准的支持,如更严格的密码策略和会话管理机制等。 ##...
- **RESTeasy集成**:RESTeasy是由JBoss成员Bill Burke开发的一个REST实现,它也被集成到Seam 2.1中,进一步增强了框架对RESTful应用的支持。 - **RESTful应用示例**:通过集成JAX-RS和RESTeasy,Seam 2.1能够提供更...
Seam 2.1 安全模块框架是一个强大的工具,为使用 Seam 开发的应用程序提供了全面的安全管理和认证机制。框架的核心特性包括: 1. **安全验证**:Seam 提供了一个可扩展的安全验证层,基于 Java Authentication and ...
### 基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》全书知识点概览 #### 一、Seam框架简介 Seam框架是JBoss组织推出的一个开源项目,旨在简化企业级应用开发,通过...
Seam为 应 业务业业 义 种统 组 你的 用程序中所有的 定 了一 一的 件模型。 Seam组件可能是 态义 关关 态 有状 的,包含与几个定 良好的上下文中任何一个相 的状 , 包括长开间运行上 下文、持久化上下文、业务流程...
### JBoss Seam 2.1版本开发参考知识点 #### 一、JBoss Seam 框架简介 **JBoss Seam** 是一个企业级Java Web应用框架,它简化了基于Java平台的应用程序开发过程。该框架提供了强大的上下文管理功能、会话管理、...
### 基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》摘要分析 #### 核心概念:Seam框架概述 Seam框架是一款革命性的Web应用开发框架,它将标准的Java EE技术与一系列...
整理自jboss seam 中文站,压缩为chm格式,便于广大jboss seam爱好者阅读,所有版权归jboss seam中文站所有。
#### 第二章:用 Seam-gen 起步 本章介绍了如何使用 Seam-gen 快速构建 Seam 应用程序。 - **准备活动**:准备开发环境,包括安装必要的软件和配置工具。 - **建立一个新的 Eclipse 项目**:使用 Eclipse 创建一个新...
**二、Seam核心概念** 1. **组件(Components)**: Seam的核心是组件模型,它允许开发者定义和管理应用中的对象。组件可以是简单的Java类,也可以是EJB或JSF Managed Beans。Seam自动管理组件的生命周期,包括创建、...
#### 二、SEAM 入门指南 ##### 1.1 尝试 SEAM - **环境搭建**: - 在 **JBoss AS** 上运行示例。 - 在 **Tomcat服务器** 上运行示例。 - 运行单元测试验证功能。 ##### 1.2 第一个例子:注册示例 - **代码...
中文版的Seam_2.0_Reference_zh_CN.pdf为开发者提供了详细的框架功能和用法,覆盖了组件、事件处理、安全、国际化等各个方面,是学习和理解Seam不可或缺的资源。 **2. RichFaces** RichFaces 是一套基于JSF的组件...
6. **安全性**:Seam提供了内置的安全机制,如身份验证和授权,使得开发人员能够快速为应用添加安全特性。 7. **国际化与本地化**:Seam支持多语言环境,对于中英文双语版本的书籍,这为开发者提供了跨越语言障碍的...
Seam Security是针对Java Web应用程序的安全框架,它是JBoss Seam项目的一部分,提供了全面的安全解决方案,包括...在日益增长的网络威胁环境中,采用像Seam Security这样的安全框架是确保Web应用程序安全的关键步骤。
在这个“seam需要的jar包”压缩包中,包含了运行和开发Seam应用程序所需的各种库文件。 首先,Seam框架的核心依赖于JSF,这是Java EE中的一个用户界面组件框架,用于构建交互式Web应用。JSF提供了模型-视图-控制器...
seam下一代web开发框架
#### 2.1 第一部分:起步使用Seam - **第1章:Seam统一Java EE 3**:介绍 Seam 如何整合 Java EE 3 技术,形成统一的应用开发平台。 - **第2章:将Seam-Gentoo投入工作**:展示如何在 Gentoo Linux 系统上安装和配置...
seam 中文文档 pdf 格式 JSF+EJB3.0快速开发框架Seam的中文版向导。。。