15.4. 身份管理
身份管理功能提供了一组标准的API接口,用来管理Seam应用程序的用户和角色。它不管这些用户和角色数据在后台是如何存储的(例如数据库、LDAP等等)。身份管理API的核心部分就是identityManager组件。该组件提供了所有常用的相关功能,例如新建用户、修改用户、删除用户、给用户授权一个角色或者取消用户拥有的某个角色、用户密码修改、设置用户帐号是否有效、验证用户权限以及列出所有用户和角色。
在使用identityManager之前,必须配置一个或多个
IdentityStore。这些组件负责具体的数据存储,不管相关数据是存储在数据库中还是LDAP服务器中,或是其他什么东西里面。
15.4.1. 配置IdentityManager
identityManager组件允许配置多个不同的存储身份信息的数据源。这就意味着,你可以将用户身份信息存储在LDAP目录下,同时将角色信息存储在相关的数据库中。
Seam支持两种IdentityStore
的实现方式:1、JpaIdentityStore,将用户身份和角色信息存储在数据库中。如果没有明确指定存储方式,那么就使用这种实现。2、
LdapIdentityStore,将相关信息存储在LDAP目录下。
identityManager组件拥有两个可以设置的属性:
identityStore
和roleIdentityStore
。这两个属性的值都必须是一个EL表达式,表达式中的对象必须为实现了IdentityStore接口的Seam组件。上面已经提到过,如果没有明确设置,那么默认会使用JpaIdentityStore方式。如果你只设置了
identityStore属性的值,那么
roleIdentityStore的值会默认设置为与identityStore属性值相同。例如
:
<!----><security:identity-manager identity-store="#{ldapIdentityStore}"/>
<security:identity-manager identity-store="#{ldapIdentityStore}" role-identity-store="#{jpaIdentityStore}"/>
15.4.2. JpaIdentityStore
在数据库中存储权限认证相关的用户与角色信息,并且与数据库中表结构的灵活性很大。只需要使用几个注解,就能让实体中的相关属性与角色用户等关联上
15.4.2.1. 配置JpaIdentityStore
JpaIdentityStore
配置里面需要指明用户类与角色类。这两个类都必须为实体,并且在数据库中是用来存储用户和角色信息。下面是components.xml
文件中的配置方法:
<!----><security:jpa-identity-store user-class="org.jboss.seam.example.seamspace.MemberAccount" role-class="org.jboss.seam.example.seamspace.MemberRole"/>
15.4.2.2. 配置实体Entities
实体中需要用注解支出用户与角色信息。下表中列举了这些注解以及注解的相关描述:
表 15.1. 用户实体中使用到的注解
注解 |
|
描述 |
@UserPrincipal |
必须 |
指定用户名 |
@UserPassword |
必须 |
指定密码,可以用来指定密码的hash存储规则(md5、sha.) 例如:
<!---->@UserPassword(hash = "md5")
public getPasswordHash() { return passwordHash; }
|
@UserFirstName |
可选 |
看名字就知道是什么意思了吧 |
@UserLastName |
可选 |
同上 |
@UserEnabled |
可选 |
布尔值,如果没有写出这个注解,那么所有用户帐号都是可用的 |
@UserRoles |
必须 |
这个注解下面会详细介绍 |
表 15.2. 角色实体中用到的注解
注解 |
|
描述 |
@RoleName |
必须 |
|
@RoleGroups |
可选 |
|
@RoleConditional |
可选 |
指出这个角色是否依赖其他角色。关于角色依赖的部分,后面会详细介绍。 |
15.4.2.3. Entity Bean实例
上面提到过,这部分功能被设计成尽量灵活。下面就举出了几个不同表结构的例子。
15.4.2.3.1. 最简单的表结构
在这个最简单的例子里面,用户和角色表通过一个多对多关系来关联。中间表的名字为UserRoles。
15.4.2.3.2. 复杂的表结构示例
下面这个例子是从上面那个简单的例子扩展来的,并且加入了角色分组支持。
<!---->@Entity
public class User {
private Integer userId;
private String username;
private String passwordHash;
private Set<Role> roles;
private String firstname;
private String lastname;
private boolean enabled;
@Id @GeneratedValue
public Integer getUserId() { return userId; }
public void setUserId(Integer userId) { this.userId = userId; }
@UserPrincipal
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
@UserPassword(hash = "md5")
public String getPasswordHash() { return passwordHash; }
public void setPasswordHash(String passwordHash) { this.passwordHash = passwordHash; }
@UserFirstName
public String getFirstname() { return firstname; }
public void setFirstname(String firstname) { this.firstname = firstname; }
@UserLastName
public String getLastname() { return lastname; }
public void setLastname(String lastname) { this.lastname = lastname; }
@UserEnabled
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
@UserRoles @ManyToMany(targetEntity = Role.class)
@JoinTable(name = "UserRoles", joinColumns = @JoinColumn(name = "UserId"), inverseJoinColumns = @JoinColumn(name = "RoleId"))
public Set<Role> getRoles() { return roles; }
public void setRoles(Set<Role> roles) { this.roles = roles; }
}
@Entity
public class Role {
private Integer roleId;
private String rolename;
private boolean conditional;
@Id @Generated
public Integer getRoleId() { return roleId; }
public void setRoleId(Integer roleId) { this.roleId = roleId; }
@RoleName
public String getRolename() { return rolename; }
public void setRolename(String rolename) { this.rolename = rolename; }
@RoleConditional
public boolean isConditional() { return conditional; }
public void setConditional(boolean conditional) { this.conditional = conditional; }
@RoleGroups @ManyToMany(targetEntity = Role.class)
@JoinTable(name = "RoleGroups", joinColumns = @JoinColumn(name = "RoleId"), inverseJoinColumns = @JoinColumn(name = "GroupId"))
public Set<Role> getGroups() { return groups; }
public void setGroups(Set<Role> groups) { this.groups = groups; }
}
15.4.2.4. JpaIdentityStore事件
会产生一些调用某些IdentityManager方法的事件。
15.4.2.4.1. JpaIdentityStore.EVENT_PRE_PERSIST_USER
这个事件在调用IdentityManager.createUser()
方法的时候被激活。在用户实体被保存进入数据库之前,这个事件被激活,并且将JpaIdentityStore
中配置的用户实体类的一个实例作为参数传递。
如果想要在createUser()
功能以外添加额外的信息到实体中去,那么可以编写一个该事件的观察器来实现。
15.4.2.4.2. JpaIdentityStore.EVENT_USER_CREATED
这个事件也是在IdentityManager.createUser()
方法被调用的时候激活,不过是在用户数据被保存进入数据库之后。就像EVENT_PRE_PERSIST_USER事件一样,该事件同样也携带一个实体的实例作为参数。如果你想要在保存用户实体到数据库的同时保存一些相关的其他用户信息到数据库,例如用户的联系方式等,那么你可以编写一个该事件的观察器来实现。
15.4.2.4.3. JpaIdentityStore.EVENT_USER_AUTHENTICATED
这个事件在调用IdentityManager.authenticate()
的时候被激活。用户实例会作为参数跟随这个事件传递。如果想要在用户被验证的同时读取与用户相关的其他属性,那么可以编写一个观察器来实现。
15.4.4. 编写你自己的IdentityStore
只需要编写一个实现了org.jboss.seam.security.management.IdentityStore
接口的类。具体实现可以参考JavaDoc里面的方法说明,里面介绍了所有实现接口时必须实现的方法。
15.4.5. 使用身份管理模块进行验证
如果你想要在你的Seam程序里面使用身份管理模块,你无须单独编写一个验证组件。只要在components.xml文件里identity配置部分指定authenticator-method,
SeamLoginModule就会默认调用
IdentityManager来对登录到你编写的程序的用户进行身份验证。
15.4.6. 使用IdentityManager
IdentityManager可以通过两种方式调用。可以是通过注入一个实例的方式:
<!---->@In IdentityManager identityManager
或者调用静态的instance()
方法:
<!---->IdentityManager identityManager = IdentityManager.instance();
下表中介绍了IdentityManager接口中用到的方法:
Table 15.4. 身份管理API
方法 |
返回值 |
介绍 |
createUser(String name, String password) |
boolean |
用传入的用户名和密码创建一个用户账户,创建成功返回true,否则返回false。 |
deleteUser(String name) |
boolean |
|
createRole(String role) |
boolean |
|
deleteRole(String name) |
boolean |
|
enableUser(String name) |
boolean |
|
disableUser(String name) |
boolean |
|
changePassword(String name, String password) |
boolean |
|
isUserEnabled(String name) |
boolean |
|
grantRole(String name, String role) |
boolean |
|
revokeRole(String name, String role) |
boolean |
|
userExists(String name) |
boolean |
|
listUsers() |
List |
所有用户列表,用户名首字母排序 |
listUsers(String filter) |
List |
|
listRoles() |
List |
|
getGrantedRoles(String name) |
List |
传入参数为用户名,列出该用户的所有角色List |
getImpliedRoles(String name) |
List |
列出用户的所有角色,递归方式列出所有父角色与子角色。 |
authenticate(String name, String password) |
boolean |
|
addRoleToGroup(String role, String group) |
boolean |
|
removeRoleFromGroup(String role, String group) |
boolean |
|
listRoles() |
boolean |
|
想要调用身份管理接口,需要调用方法的用户拥有相应的权限。下面这个表列出了IdentityManager
中各方法所需的权限。对象权限这一列中的字符串值。
Table 15.5. 身份管理所需权限
方法 |
对象权限 |
操作权限 |
createUser() |
seam.user |
create |
deleteUser() |
seam.user |
delete |
createRole() |
seam.role |
create |
deleteRole() |
seam.role |
delete |
enableUser() |
seam.user |
update |
disableUser() |
seam.user |
update |
changePassword() |
seam.user |
update |
isUserEnabled() |
seam.user |
read |
grantRole() |
seam.user |
update |
revokeRole() |
seam.user |
update |
userExists() |
seam.user |
read |
listUsers() |
seam.user |
read |
listRoles() |
seam.role |
read |
addRoleToGroup() |
seam.role |
update |
removeRoleFromGroup() |
seam.role |
update |
下面这段规则设置代码列出了将所有身份管理相关的权限赋予admin角色的例子:
<!---->rule ManageUsers
no-loop
activation-group "permissions"
when
check: PermissionCheck(name == "seam.user", granted == false)
Role(name == "admin")
then
check.grant();
end
rule ManageRoles
no-loop
activation-group "permissions"
when
check: PermissionCheck(name == "seam.role", granted == false)
Role(name == "admin")
then
check.grant();
end
分享到:
相关推荐
Seam 2.1 安全模块框架是一个强大的工具,为使用 Seam 开发的应用程序提供了全面的安全管理和认证机制。框架的核心特性包括: 1. **安全验证**:Seam 提供了一个可扩展的安全验证层,基于 Java Authentication and ...
Seam 2.1 是一款强大的企业级 Java 开发框架,它为开发人员提供了一种简单而高效的方式来构建复杂的 Web 应用程序。相较于 Seam 2.0 版本,Seam 2.1 在权限验证方面进行了大量的增强,引入了更多的功能和改进,以...
Seam 2.1 GA版本是Seam框架的一个重要更新,该版本带来了许多新的特性和改进,使得Seam更加适合于现代的企业级应用开发。 #### 二、支持Wicket ##### 技术细节 - **Seam组件与Wicket的整合**:Seam 2.1允许开发者...
**2.1.2版本** 是Seam框架的一个重要更新,它引入了许多新特性与改进,包括但不限于更好的性能优化、增强的安全性支持以及对现代Web开发实践的支持。此外,此版本还包含了对Seam核心功能的改进,例如对页面流控制的...
- 提供了全面的Seam框架技术文档和实例代码。 - 强调实践操作,适合自学和教学使用。 - 能够帮助开发者快速掌握Seam框架的关键技术和应用场景。 - **适用对象**: - Java EE开发者,特别是那些希望提高自己在...
Seam 是一种业级 企 Java 的应规用程序框架。它的灵感源自下列原 : 只有一种“工具” Seam为 应 业务业业 义 种统 组 你的 用程序中所有的 定 了一 一的 件模型。 Seam组件可能是 态义 关关 态 有状 的,包含与几...
### 基于Seam2.1的最新力作《Seam Framework: Experience the Evolution of Java EE, 2nd Edition》摘要分析 #### 核心概念:Seam框架概述 Seam框架是一款革命性的Web应用开发框架,它将标准的Java EE技术与一系列...
Seam Security 中的验证特性是基于JAAS (Java Authentication and Authorization Service)开发的,它提供了用来进行用户身份认证的高度可配置的接口。然而,针对复杂多变的验证需求,Seam ... 标签:安全相关框架
### Seam框架核心知识点详解 #### 一、Seam框架简介 Seam,全称为JBoss Seam,是一款基于Java EE 5的技术栈构建的应用框架。它通过整合JSF(JavaServer Faces)与EJB 3.0(Enterprise JavaBeans 3.0)组件,并充分...
整理自jboss seam 中文站,压缩为chm格式,便于广大jboss seam爱好者阅读,所有版权归jboss seam中文站所有。
Seam是一个针对Java开发的全栈式框架,旨在简化开发过程,提高开发效率。它适应了快速开发和简化架构的需求,与传统的Java框架相比,Seam具有更简洁的层次结构和强大的组件机制。 首先,Seam的核心设计理念在于减少...
seam+richfaces环境框架的配置文件,经过我多次尝试才配置好的环境配置文件,很有用,适合刚接触这些技术的初学者,希望大家支持!
中文版的Seam_2.0_Reference_zh_CN.pdf为开发者提供了详细的框架功能和用法,覆盖了组件、事件处理、安全、国际化等各个方面,是学习和理解Seam不可或缺的资源。 **2. RichFaces** RichFaces 是一套基于JSF的组件...
【JBoss Seam 2.0文档详解】 JBoss Seam 是一个开源的企业级开发框架,它旨在简化Java EE应用的开发过程,特别是在Web和富互联网应用程序(Rich Internet Applications, RIA)领域。Seam 2.0是其重要的版本,提供了...
4. **安全性和身份验证**:Seam提供了内置的安全框架,可以轻松集成到JSF应用中,实现用户身份验证和授权。 5. **国际化和本地化**:Seam与JSF结合,使得应用的国际化和本地化变得更加简单,开发者可以通过Seam的...
`seam-gen`命令的工作原理类似于Ruby语言中的“scaffold”概念,它通过一系列预定义的模板和规则,自动生成包含基本功能模块的代码框架,从而显著提高开发效率。在使用`seam-gen`之前,需要确保系统中已安装了Ant ...
JBoss Seam 是一款基于 Java 的企业级应用开发框架,它简化了应用程序的开发过程,特别是那些涉及复杂的用户交互、业务逻辑以及数据处理的应用。Seam 结合了 JavaServer Faces (JSF)、Java Persistence API (JPA)、...
文档提供了丰富的教程内容,覆盖了Seam框架的基本使用方法到高级特性,适合不同程度的学习者进行参考学习。 ##### 1. 使用Seam示例 - **在JBoss AS上运行示例**:这部分介绍了如何在JBoss Application Server上...
JBoss Seam是一个高度集成的应用框架,旨在简化企业级Java应用的开发过程。Seam2.0版本提供了丰富的功能来支持面向组件的编程模式,并且它紧密集成了JavaServer Faces (JSF) 和 Enterprise JavaBeans (EJB) 技术。 ...