查看文章 |
Seam 2.1中的安全升级
2008-06-05 20:48
Seam安全升级 by Shane Bryzak,翻译:JSF中文技术文摘 Article permalink: http://shane.bryzak.com/articles/seam_security_gets_an_upgrade 即将到来的 JBoss Seam 2.1.0.GA 发布版本将包含一些新的功能和增强的安全特性,这些安全特性包括 Identity Management, 基于ACL的权限, 和 Permission Management, 还 有强类型(strongly-typed)的安全注解。在这篇文章中,我将结合在SeamSpace示例(在Seam发布包的/examples/seamspace目录下)来讲解下这些新的安全特性。 如果你想自己来运行下SeamSpace示例程序,下面有些建议来指导你如何做: 1) 首先,确保你安装了JDK 1.5,还有 Apache Ant(最近发布版本) 2) 下载并安装 JBoss AS 4.2.2, 下载地址: http://www.jboss.org/jbossas/downloads/ 3) 下载并且解压缩Seam的2.1每日建构版本,下载地址: http://www.seamframework.cn/Download (如果你具有探索精神,可以从SVN中检出最新版本,地址: http://anonsvn.jboss.org/repos/seam/trunk/) 4) 编辑Seam目录中的 build.properties 文件,修改你的 JBoss AS 安装目录 5) 导航到 examples/seamspace 目录,运行 'ant' 6) 在 JBoss bin目录下运行run脚步来启动JBoss AS 7) 在 JBoss AS 启动后,打开 http://localhost:8080/seam-space 现在我们开始看看新的 Identity Management 特性。 Identity Management 那么什么是 Identity Management 呢? 直到现在,Seam只提供了使用内建的组件来做用户验证(Identity 组件)。Seam没有提供的是一个用于创建和管理实际用户帐户的API, 你可以使用这些API来验证用户信息,这留给了开发者。Identity Management通过提供这样一个API来填补了这个空白,这个API努力使用一致的方式来管理用户和角色,而不用考 虑他们存储在那里。无论他们是作为记录保存在关系数据库中还是作为实体保存在LDAP目录中,Identity Management都在Seam程序中提供了统一标准的API来创建,更新,和删除 用户和角色。 刚才所说的 Identity Management API 就是 IdentityManager 组件。这个组件暴露了一些identity management的操作。为了让你更多的了解下这个特性,下面列出了一些它具有 的函数: * createUser(String username, String password) * deleteUser(String name) * enableUser(String name) * disableUser(String name) * changePassword(String name, String password) * isUserEnabled() * grantRole(String name, String role) * revokeRole(String name, String role) * createRole(String role) * deleteRole(String role) * userExists(String name) * roleExists(String name) * listUsers() * authenticate(String username, String password) 从上表中你可以看到,大多数的函数都和操作系统安全相关的命令同义(假设你属性unix/linux),就像:adduser,deluser 等待。 Configuring IdentityManager IdentityManager的配置是相当简单的 -- 它需要和一个或则两个认证中心(identity stores)一起配置。一个identity store 用于所有用于相关的操作,另外一个用于角色相关 的操作。如果你的用户和角色相关信息都保存在同一个存储中心中(例如一个数据库),这样只需要一个identity store就可以了,这一个identity store用作用户和角色相关的 操作。这听起来好像有点奇怪,当处理复杂的安全需求时,这有相当大的伸缩性。 例如这样一个场景:从LDAP中验证用户,但是从一个关系数据库中载入用户的角色信息。 每个 IdentityStore 实现都知道如何与一个特别的存储中心打交道。Seam提供了两个现成的 IdentityStore 实现,JpaIdentityStore 和 LdapIdentityStore, 分别用于数据库和 基于LDAP的安全验证。如果IdentityManager没有配置identity stores,那么它就使用默认值JpaIdentityStore。我们以后在来讲解如何使用LdapIdentityStore,现在这篇文章中 我们就只关注JpaIdentityStore。 JpaIdentityStore 这个 IdentityStore 实现可以让你把用户帐户信息保存在数据库中。通过应用特定的注解到代表用户和角色的实体bean上,JpaIdentityStore可以使用这些实体来管理用户数据库 中的用户信息。 我们来看看用来保存用户帐户信息的 MemberAccount 实体 bean。 下面的代码为了排版被截断了 : @Entity @Table(uniqueConstraints = @UniqueConstraint(columnNames = "username")) public class MemberAccount implements Serializable { // snip field and key declarations @NotNull @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; } @UserEnabled public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } @UserRoles @ManyToMany(targetEntity = MemberRole.class) @JoinTable(name = "AccountMembership", joinColumns = @JoinColumn(name = "AccountId"), inverseJoinColumns = @JoinColumn(name = "MemberOf")) public Set<MemberRole> getRoles() { return roles; } public void setRoles(Set<MemberRole> roles) { this.roles = roles; } } 就如我们看到的,在bean的属性访问方法中有一些附加的注解,这些注解告诉 JpaIdentityStore 如何与特定的实体bean交互。我们下面来详细的看看这些注解: * @UserPrincipal - 该注解表明该属性包含用户的主要属性(i.e. 用户名称) * @UserPassword - 该注解表明该属性包含用户的密码。把用户密码保存为普通文本通常不是一个好的注意,因此这个注解支持使用hash算法。该算法用来产生一个用户密码 的hash值,然后会把hash值保存到数据库中。 * @UserEnabled - 这个是可选的,用户指示该用户帐户是否是启用的,默认值为启用所有的帐户。 * @UserRoles - 这个注解指示该用户所属的角色组。 这里还有一组类似的注解来配置一个用来保存角色的实体bean。还可以把角色信息和用户信息保存在同一个表中,通过鉴别器来区分,请参考Seam的文档来了解相关信息。 Alternatively, it is possible to store role records in the same table as users (which then becomes self-referencing via a one-to-many relationship to itself) by specifying one of the columns as a discriminator (determining whether the record represents a user or a role). Using IdentityManager 我们来看看SeamSpace示例, 看看Identity management是如何工作的 ![]() 从上图,SeamSpace的主页,我们可以看到一个让用户注册的'SIGN UP'链接。在注册页面用户可以输入一些帐户信息来注册,然后可以用来登陆。注册的程序使用IdentityManager 来创建新的用户帐户,然后登陆新注册的用户。看一下 RegisterAction.java 类,我们可以看到 Identity Manager 通过使用 @In 注解注入进来了: @In private IdentityManager identityManager; 更进一步,我们可以在uploadPicture()方法中看到新用户是如何被创建的 (在注册流程的最后调用了该方法,并且结束了当前的会话): @End public void uploadPicture() { (snip) new RunAsOperation() { public void execute() { identityManager.createUser(username, password); identityManager.grantRole(username, "user"); } }.addRole("admin") .run(); (snip) // Login the user identity.setUsername(username); identity.setPassword(password); identity.login(); } RunAsOperation 使用较高的优先级来执行特别的操作。在这种情况下,创建一个新用户要求当前的用户具有管理员的权限,上面的代码通过addRole()函数暂时为RunAsOperation 操作授权。在该函数的最后我们看到该用户使用用户名和密码登陆到系统中了。 Authentication 以前,Seam安全管理在认证阶段需要调用一个'authenticator' 组件,该组件用来计算用户的角色。这个认证模型当前依然支持,同时使用IdentityManager 来认证用户更合常理 ,他提供了认证功能而不用写额外的待命。请记住,要使用IdentityManager 来验证用户,只需要从components.xml文件的identity 组件配置中删除'authenticate-method'属性 就可以了: <!-- The old way of authenticating, using an authenticator component --> <!--security:identity authenticate-method="#{authenticator.authenticate}"/--> <!-- The new way to authenticate, using IdentityManager (you don't actually need to include this element, since it has no attributes now) --> <security:identity/> User Management Views 如果你使用管理员帐号登陆 SeamSpace (username/password: demo/demo),在顶部你会看到一个'Security' 连接. 点击这个连接可以用来管理其他的用户和角色: ![]() 点击第一个连接, 'Manage Users' 将会打开用户管理页面: ![]() ![]() ![]() ![]() ![]() ![]() 这里我们就结束了 identity management 特效的预览,下面来看看 permission management. Permission Management 查看这里: http://hi.baidu.com/jsfcn/blog/item/a7b399450cb94c3a87947383.html |
最近读者:







