`

seam2.1权限验证(15.4) jpa-identity-store

    博客分类:
  • Seam
阅读更多
15.4. 身份管理身份管理功能提供了一组标准的API接口,用来管理Seam应用程序的用户和角色。它不管这些用户和角色数据在后台是如何存储的(例如数据库、LDAP等等)。身份管理API的核心部分就是identityManager组件。该组件提供了所有常用的相关功能,例如新建用户、修改用户、删除用户、给用户授权一个角色或者取消用户拥有的某个角色、用户密码修改、设置用户帐号是否有效、验证用户权限以及列出所有用户和角色。
在使用identityManager之前,必须配置一个或多个IdentityStore。这些组件负责具体的数据存储,不管相关数据是存储在数据库中还是LDAP服务器中,或是其他什么东西里面。

15.4.1. 配置IdentityManageridentityManager组件允许配置多个不同的存储身份信息的数据源。这就意味着,你可以将用户身份信息存储在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. 配置JpaIdentityStoreJpaIdentityStore配置里面需要指明用户类与角色类。这两个类都必须为实体,并且在数据库中是用来存储用户和角色信息。下面是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。

@Entity
public class User {
private Integer userId;
private String username;
private String passwordHash;
private Set<Role> roles;

@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; }

@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;

@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; }
}


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. 使用IdentityManagerIdentityManager可以通过两种方式调用。可以是通过注入一个实例的方式:
@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                    传入参数为用户名,列出该用户的所有角色ListgetImpliedRoles(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
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics