使用 Acegi 保护 Java 应用程序: 续二
使用 Acegi 保护 Java 应用程序: 续二
?
了解了 Acegi 安全系统(Acegi Security System)的 基础知识 后,我们将介绍该系统的更加高级的应用。在本文中,Bilal Siddiqui 向您展示了如何结合使用 Acegi 和一个 LDAP 目录服务器,实现灵活的具有高性能的 Java? 应用程序的安全性。还将了解如何编写访问控制策略并将其存储在 ApacheDS 中,然后配置 Acegi 使其与目录服务器交互,从而实现身份验证和授权的目的。
?
这期共分三部分的系列文章介绍了如何使用 Acegi 安全系统保护 Java 企业应用程序。在 本系列第一篇文章 中,我介绍了 Acegi 并解释了如何使用安全过滤器实现一个简单的基于 URL 的安全系统。在第二篇文章中,我将讨论 Acegi 的更加高级的应用,首先我将编写一个访问控制策略并将其存储在 ApacheDS 中,ApacheDS 是一个开源的 LDAP 目录服务器。我还将展示配置 Acegi 的方法,使它能够与目录服务器交互并实现您的访问控制策略。本文的结尾提供了一个示例应用程序,它使用 ApacheDS 和 Acegi 实现了一个安全的访问控制策略。
实现访问控制策略通常包含两个步骤:
Acegi 将减轻代码编写的工作,因此在这篇文章中,我将展示如何将用户和用户角色信息存储到 ApacheDS 中,然后实现这些信息的访问控制策略。在该系列的最后一篇文章中,我将展示如何配置 Acegi,实现对 Java 类的安全访问。
您可以在本文的任何位置 下载样例应用程序。参见 参考资料 下载 Acegi、Tomcat 和 ApacheDS,您需要使用它们运行样例代码和示例应用程序。
?
?
?
?
在图 1 中,根节点的名称为 org。根节点可以封装与不同企业有关的数据。例如,本系列第 1 部分开发的制造业企业被显示为 org 节点的直接子节点。该制造业企业具有两个名为 departments 和 partners 的子节点。
partners 子节点封装了不同类型的合作伙伴。图 1 所示的三个分别为 customers、employees 和 suppliers。注意,这三种类型的合作伙伴其行为与企业系统用户一样。每一种类型的用户所扮演的业务角色不同,因此访问系统的权利也不同。
?
类似地,departments 节点包含该制造业企业的不同部门的数据 —— 例如 engineering 和 marketing 字节点。每个部门节点还包含一组或多组用户。在 图 1 中,engineers 组是 engineering 部门的子节点。
假设每个部门的子节点表示一组用户。因此,部门节点的子节点具有不同的用户成员。例如,设计部门的所有工程师都是 engineering 部门内 engineers 组的成员。
?
最后,注意 图 1 中 departments 节点的最后一个子节点。specialUser 是一名用户,而非一组用户。在目录设置中,像 alice 和 bob 之类的用户一般都包含在 partners 节点中。我将这个特殊用户包含在 departments 节点中,以此证明 Acegi 允许用户位于 LADP 目录中任何地点的灵活性。稍后在本文中,您将了解如何配置 Acegi 以应用 specialUser。
?
?
首先,注意图 2 中根节点的 DN。它的 DN 为 dc=org,这是与 org 根节点相关的属性值对。每个节点都有若干个与之相关的属性。dc 属性代表 “domain component” 并由 LDAP RFC 2256 定义(参见 参考资料 中有关官方 RFC 文档的链接),LDAP 目录中的根节点通常表示为一个域组件。
?
每个 LDAP 属性是由 RFC 定义的。LDAP 允许使用多个属性创建一个 DN,但是本文的示例只使用了以下 4 个属性:
dc(域组件) o(组织) ou(组织单元) uid(用户 ID)示例使用 dc 表示域,用 o 表示组织名称,ou 表示组织的不同单元,而 uid 表示用户。
?
由于 org 是根节点,其 DN 只需指定自身的名称(dc=org)。比较一下,manufacturingEnterprise 节点的 DN 是 o=manufacturingEnterprise,dc=org。当向下移动节点树时,每个父节点的 DN 被包含在其子节点的 DN 中。
?
![]()
![]()
回页首
清单 1 编辑了 examplePartitionConfiguration bean 的两个属性:
一个属性名为 suffix,它定义根条目的 DN。本文的 源代码下载 部分包含了编辑模式的 server.xml 文件。如果希望继续学习本示例,请将 server.xml 文件从源代码中复制到您的 ApacheDS 安装目录中的正确位置,即 conf 文件夹。
图 3 所示的屏幕截图展示了在 ApacheDS 中创建根节点后,JXplorer 是如何显示该根节点的:
图 3. JXplorer 显示根节点
?
将 LDIF 文件导入到 ApacheDS 之后,JXplorer 将显示用户节点和部门节点树,如 图 1 所示。现在您可以开始配置 Acegi,使其能够与您的 LDAP 服务器通信。
查看一下清单 2,您曾经为 APF 提供了 4 个参数。您只需在 LDAP 服务器中为存储重新配置第一个参数(authenticationManager)即可。其他三个参数保持不变。
在清单 3 中,org.acegisecurity.providers.ProviderManager 是一个管理器类,它管理 Acegi 的身份验证过程。为此,身份验证管理器需要一个或多个身份验证提供者。您可以使用管理器 bean 的提供者属性来配置一个或多个提供者。清单 3 只包含了一个提供者,即 LDAP 身份验证提供者。
LDAP 身份验证提供者处理所有与后端 LDAP 目录的通信。您必须对其进行配置,下一节内容将讨论该主题。
![]()
![]()
回页首
搜索查询的参数
清单 6 展示了 userSearch bean 是 org.acegisecurity.ldap.search.FilterBasedLdapUserSearch 类的一个实例,该类的构造函数具有三个参数。第一个参数指定 authenticator 在哪个节点中搜索用户。第一个参数的值为 ou=departments,该值是一个 RDN,指定了 图 2 所示的 departments 节点。
第二个参数 (uid={0}) 指定了一个搜索过滤器。由于使用 uid 属性指定用户,因此可以通过查找 uid 属性具有特定值的节点来查找用户。正如您所料,花括号里面的 0 向 Acegi 表示使用进行身份验证的用户的用户名(本例中为 specialUser)替换 {0}。
第三个参数是对讨论 清单 5 中的 BindAuthenticator 构造函数时引入的相同初始上下文的引用。回想一下,当指定了初始上下文后,稍后将在该初始上下文节点的子节点内进行所有的搜索操作。注意,应将指定为 清单 5 中第一个参数(ou=departments)的值的 RDN 前加到初始上下文。
除了这三个构造器参数,清单 6 所示的 userSearch bean 还具有一个名为 searchSubtree 的属性。如果将其值指定为 true,搜索操作将包括节点的子树(即所有子节点、孙节点、孙节点的子节点等),该节点被指定为构造函数的第一个参数的值。
authenticator bean 的配置完成后,下一步将查看 populator bean 的配置,如 清单 4 所示。
![]()
![]()
回页首
无论 APF 使用属性文件进行内部的身份验证还是与 LDAP 服务器进行通信,步骤 1 到步骤 9 与第 1 部分是相同的。这里简单描述了前 9 个步骤,您可以从步骤 10 开始继续学习特定于 LDAP 的事件:
不论使用何种身份验证方法,最后三个步骤是相同的(步骤21、21 和 23)。
在清单 9 中,IF 包含三个参数。其中第一个和第三个参数与第 1 部分中最初配置的参数相同。这里添加了第二个参数(名为 accessDecisionManager 的 bean)。
accessDecisionManager bean 负责指定授权决策。它使用清单 9 中第三个参数提供的访问控制定义来指定授权(或访问控制)决策。第三个参数是 objectDefinitionSource。
在清单 10 中,accessDecisionManager bean 是 org.acegisecurity.vote.AffirmativeBased 类的实例。accessDecisionManager bean 只包含一个参数,即投票者(voter)列表。
在 Acegi 中,投票者确定是否允许某个用户访问特定的资源。当使用 accessDecisionManager 查询时,投票者具有三个选项:允许访问(access-granted)、拒绝访问(access-denied),如果不确定的话则放弃投票(abstain from voting)。
不同类型的访问决策管理器解释投票者决策的方法也有所不同。清单 10 所示的 AffirmativeBased 访问决策管理器实现了简单的决策逻辑:如果任何投票者强制执行肯定投票,将允许用户访问所请求的资源。
![]()
![]()
回页首
结束语
在本文中,您了解了如何将用户和业务角色信息托管在 LDAP 目录中。您还详细了解了配置 Acegi 的方法,从而与 LDAP 目录交互实现访问控制策略。在本系列最后一期文章中,我将展示如何配置 Acegi 来保护对 Java 类的访问。
?
?
?
实例程序见附件
?
?
?
?
未完待续!
?
?
?
?
?
?