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属性值相同。例如
:
15.4.2. JpaIdentityStore
在数据库中存储权限认证相关的用户与角色信息,并且与数据库中表结构的灵活性很大。只需要使用几个注解,就能让实体中的相关属性与角色用户等关联上
15.4.2.1. 配置JpaIdentityStore
JpaIdentityStore
配置里面需要指明用户类与角色类。这两个类都必须为实体,并且在数据库中是用来存储用户和角色信息。下面是components.xml
文件中的配置方法:
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. 复杂的表结构示例
下面这个例子是从上面那个简单的例子扩展来的,并且加入了角色分组支持。
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可以通过两种方式调用。可以是通过注入一个实例的方式:
或者调用静态的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角色的例子: