Seam 2.1 安全模块框架 文档翻译 004

15.4. 身份管理

身份管理功能提供了一组标准的API接口,用来管理Seam应用程序的用户和角色。它不管这些用户和角色数据在后台是如何存储的(例如数据库、LDAP等等)。身份管理API的核心部分就是identityManager组件。该组件提供了所有常用的相关功能,例如新建用户、修改用户、删除用户、给用户授权一个角色或者取消用户拥有的某个角色、用户密码修改、设置用户帐号是否有效、验证用户权限以及列出所有用户和角色。

在使用identityManager之前,必须配置一个或多个IdentityStore。这些组件负责具体的数据存储,不管相关数据是存储在数据库中还是LDAP服务器中,或是其他什么东西里面。

15.4.1. 配置IdentityManager

identityManager组件允许配置多个不同的存储身份信息的数据源。这就意味着,你可以将用户身份信息存储在LDAP目录下,同时将角色信息存储在相关的数据库中。

Seam支持两种IdentityStore的实现方式:1、JpaIdentityStore,将用户身份和角色信息存储在数据库中。如果没有明确指定存储方式,那么就使用这种实现。2、LdapIdentityStore,将相关信息存储在LDAP目录下。

identityManager组件拥有两个可以设置的属性:identityStoreroleIdentityStore。这两个属性的值都必须是一个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.usercreate
deleteUser()seam.userdelete
createRole()seam.rolecreate
deleteRole()seam.roledelete
enableUser()seam.userupdate
disableUser()seam.userupdate
changePassword()seam.userupdate
isUserEnabled()seam.userread
grantRole()seam.userupdate
revokeRole()seam.userupdate
userExists()seam.userread
listUsers()seam.userread
listRoles()seam.roleread
addRoleToGroup()seam.roleupdate
removeRoleFromGroup()seam.roleupdate

下面这段规则设置代码列出了将所有身份管理相关的权限赋予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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值