Java Solaris 加入Sun中国技术社区 我的社区 注册说明
 
JDK 6.0 API 中文版
 
 
 
 
 
Java API 文档中文版
使用 Sun Java System Access Manager 开发安全应用程序,第 1 部分:基本授权
 
By Robert Skoczylas 和 Marina Sum, 1/29/08  

多年以来,通过使用健壮的解决方案来保护 Web 应用程序的需求与日俱增。为确保安全性满足需要,大多数提供在线 Web 服务的企业都在以下两个服务级别上实现了安全性:

  • 验证 —— 确保用户符合所声称的身份。
  • 授权 —— 确认用户对要访问的资源拥有有相应的权限。

要满足服务级别需求,您需要进行详细周密的架构设计,并完成大量的实现工作。

本文是系列文章的第 1 部分,将介绍如何使用 Sun Java System Access Manager(以后称为 Access Manager)来满足虚构的医疗保险公司 EB Health 的授权需求。Access Manager 是一个企业平台,它使用验证、单点登录和授权功能来保护 Web 应用程序和服务。EB Health 需求的完整实施基于 Access Manager 6.3 (Sun Java Enterprise System 2005Q2)标准、现成的功能和自定义扩展,并可移植到 Access Manager 7.1 (Sun Java Enterprise System 5)—— 而无需修改源代码或配置

第 2 部分 将讨论如何使用基于层次的资源模型以及 .NET 应用程序的互操作 Web 服务来扩展 Access Manager 授权。

目录

需求
架构
细粒度访问级别授权
Claims 应用程序中的安全性
结束语
致谢
参考资料

 

所有 EB Health 应用程序均采用两层安全模型:Web 层和 Enterprise JavaBeans (EJB) 层。

授权模型采用基于角色的访问控制(RBAC)设计,它限制了对应用程序中的某些部分的访问。这种模型满足以下三个要求:

  • 所有经过验证的用户进行访问
  • 基于角色对应用程序 URI 进行访问
  • 基于角色的应用程序组件(Java EE 组件、表单字段、Portlet)进行访问

Access Manager 可实现集中验证、策略评估服务以及动态访问管理控制。此外,还通过通用用户界面实现了增强的可管理性。

使用 Access Manager 保护 Web 应用程序的最常见部署方案是通过基于 Policy Agent 的架构实现。在该架构中,将 Policy Agent 安装在托管应用程序并用作策略实施点 (Policy Enforcement Point, PEP) 的容器中。Policy Agent 可以在不同的模式下运行,最常见的运行模式有以下两种:

  • URL_POLICY 模式 —— 在该模式下,Policy Agent 截取所有传入的 HTTP 或 HTTPS 请求,并对其进行验证、检查会话有效性和进行授权。大多数符合行业标准的 Web 容器中都支持 Access Manager Policy Agent。
  • J2EE_POLICY 模式 —— 这种模式与 Java EE 安全模型配合使用,它将主体信息传播到 Web 和 EJB 层,以确保 Java EE 编程和声明的安全功能正常工作。大多数符合行业标准的 Java EE 容器中都支持 Access Manager Policy Agent。

图 1 是这种架构的概括视图,其中包括应用服务器、Policy Agent 和 Access Manager:

图 1:授权架构

 

尽管 Java EE 安全模型用作授权框架,但它缺少对策略定义的集中控制,因而在维护和运行时访问控制方面比较复杂。再者,Java EE 规范不允许设置资源角色的访问级别。例如,您不能将 ADMIN 角色定义为仅具有会话 Bean 的 READ ONLY 访问权限。

与之相反,图 1 所示的模型非常适用于既需要基本安全性又需要具有访问级别的复杂模型这样的应用程序。继续阅读以下内容,可以了解如何通过精细访问级别授权来自定义 Access Manager。

Access Manager Administrative Console (amconsole)是一个基于 Web 的界面,用于定义和管理资源策略。本部分介绍了如何在 Administrative Console 或命令行界面 (Command-Line Interface, CLI)中配置设置,以满足这三个授权要求。

通过采用上一部分中介绍的架构,您可以直接配置前两个要求:

  • 所有经过验证的用户进行访问
  • 基于角色对应用程序 URI 进行访问

以下是此过程的总结:

  1. 在托管应用程序的应用服务器上安装 Policy Agent 并启用 URL_POLICY 模式。
  2. 创建一个策略规则,以允许所有主体(即,经过验证的用户)访问某个 URL,例如, http://www.ebhealthinsurance.com/claims/*
  3. 对于第二个要求,重复执行步骤 1 和 2。既然如此,主体将成为有权访问所定义资源的角色。

为经过验证的用户授予访问权限
要确保能够在 EB Health 中访问 Claims 应用程序,请按如下方式定义策略、规则和主体:

  1. 在管理控制台中,单击 New Policy 选项以创建策略,然后单击 New Rule 选项以创建规则。
  2. 在图 2 所示的屏幕上,选择 URL Policy Agent (with resource name)。单击 Next 按钮。

    图 2:选择 URL Policy Agent 作为规则的服务类型
     
  3. 在图 3 所示的屏幕上:

    1. 在 Name 字段中键入 Claims Processing Application
    2. 在 Resource Name 字段中键入 Claims 应用程序的 URL,http://www.ebhealthinsurance.com/claims/*
    3. 为 Actions 下面的 GETPOST 选择 Allow。单击 Finish 按钮。

    图 3:定义规则细节
     
  4. 创建另一个主体,然后在图 4 所示的屏幕上选择 Authenticated Users 选项。单击 Next 按钮。

    图 4:选择 Authenticated Users 作为主体类型
     
  5. 在图 5 所示的屏幕上,在 Name 字段中键入 All Authenticated Users。单击 Finish 按钮。

    图 5:指定主体名称
     
    Access Manager 随后确认策略设置,如图 6 所示。

    图 6:确认策略设置
     

为应用程序 URI 授予访问权限
要满足第二个要求并仅为某些角色授予访问权限,请重复上一部分中的步骤 1 至步骤 3,然后执行以下操作:

  1. 在图 7 所示的屏幕上,选择 Access Manager Identity Subject 选项。单击 Next 按钮。

    图 7:选择 Access Manager Identity Subject 作为主体类型
     
  2. 在图 8 所示的屏幕上,在 Name 字段中键入 Admin Role,然后从 Filter 下拉菜单中选择 Role。
  3. 在 Available 下面选择 admin,然后单击 Add 将其移到 Selected 区域中。单击 Finish 按钮。单击 Finish 按钮。

    图 8:定义主体参数
     

为应用程序组件授予基于角色的访问权限
要满足第三个要求(即,为应用程序组件授予访问权限),可通过创建一个服务来自定义 Access Manager,该服务可在较低级别(比通过 URL 资源提供的安全级别要低得多)保护组件。

安全需求
EB Health 旨在以编程方式完成以下操作:

  • 仅允许某些角色访问 Claims 应用程序中的某些部分。
  • 拒绝未经授权的角色访问 Claims 应用程序中的某些部分。
  • 集中收集策略存储中的信息。

为了完成这一目标,EB Health 必须保护页面级别的资源,并为每个资源指定角色的访问级别。访问级别包括 CREATEREADUPDATEDELETEALLNONE

例如,EB Health 希望根据角色来控制对其 Claims 应用程序中的 User Profile 屏幕的访问。由于有了 Java EE 应用程序,该屏幕可以为不同的角色呈现不同的内容;这种应用程序允许用户访问资源,但限制用户可查看的内容和执行的操作(根据用户角色)。

以下两个角色可以访问 User Profile 屏幕:AdminEmployee。下面给出了安全要求和相关 UI,如图 9 所示:

  • Admin — 此角色具有整个屏幕的所有权限,其中包括 SSN [社会保险号码] 字段 ( SSN_FORM_FIELD )。相应地,在 Admin 进行访问时,User Profile 屏幕显示可编辑的所有字段值以及 Create、Update、Delete 和 Cancel 按钮。
  • Employee — 此角色具有 User Id、Email 和 Phone 字段的 UPDATE权限,但仅具有 SSN 字段的 READ 权限。在 Employee进行访问时,User Profile 屏幕只显示可编辑的 User Id、Email 和 Phone 字段,而灰显 SSN 字段以表明该角色具有 READ ONLY 访问权限。
图 9:根据 AdminEmployee 角色划分的 User Profile 屏幕访问权限

 

过程
首先,扩展 Access Manager 服务并创建一个名为 CustomClaimsAppPolicyService 的服务:

  1. 创建一个名为 CustomClaimsAppPolicyService.xml 的 XML 结构,它符合文档类型定义(Document Type Definition, DTD)sms.dtd,并指定了六个访问级别。

    此架构还描述了服务名称、服务属性及属性值。
  2. 在 CLI 中将 CustomClaimsAppPolicyService.xml 文件导入 Access Manager。键入以下内容,全部放在一行中:

    /opt/SUNWam/bin/amadmin --verbose --runasdn uid=amAdmin,ou=People,dc=ebhealthinsurance,dc=com --password admin-password --schema CustomClaimsAppPolicyService.xml

    Access Manager 随后生成以下输出:

    Info 109: Calling XML PARSER
    Info 110: XML file to import:CustomClaimsAppPolicyService.xml

    Info 103: Loading Service Schema XML CustomClaimsAppPolicyService.xml
    Service Schema XML CustomClaimsAppPolicyService.xml
    Info 115: Reading schema file :CustomClaimsAppPolicyService.xml
    Info 105: Done loading Service Schema XML: [CustomClaimsApplicationPolicyService]
    Success 0: Successfully completed.
     
    注意: 无需重新启动服务器,即可使这些更改生效。
  3. CustomClaimsAppPolicyService.propertiesCustomClaimsAppPolicyService_en.properties 复制到 Access Manager 的本地目录中,例如 /opt/SUNWam/locale

接下来,从管理控制台 CLI 中创建策略。下面的过程说明了如何创建 Claims Process Policy,并通过两种方法指定相关规则和主体。

注意:对于包含很多策略规则的大型应用程序部署来说,CLI 可能更适合一些。

从管理控制台中:

  1. 单击 New Policy 选项以创建策略。
  2. 使用所选的值填充 Policy Name 和 Description 字段。
  3. 单击 Rules 下面的 New 选项。

    Access Manager 将在缺省服务类型中显示新的自定义策略服务。
  4. 在图 10 所示的屏幕上,选择 CustomClimsApplicationPolicyService (with resource name),然后单击 Next 按钮。

    图 10:选择 CustomClaimsApplicationPolicyService 作为规则的服务类型
     
  5. 在图 11 所示的屏幕上,定义将资源与其访问级别相关联的规则,如图中所填充的内容一样。

    图 11:定义新规则的设置
     
    资源名称可以是组件、小部件、页面、URL 或需要授权的任何其他对象的字符串表示形式,以提高灵活性和简便性。.
  6. 使用以下设置为用户表单创建另一个规则:

    Service Type(服务类型)     CustomClaimsApplicationPolicyService
    Name(名称)    UserForm_A1
    Resource Name(资源名称)    UserForm
    Choose Permission(选择权限)    ALL
     
  7. 在图 12 所示的屏幕上选择 Access Manager Identity Subject 为规则分配主体(角色),此处为 Access Manager 角色。然后,按角色进行搜索以列出完整的可用角色集合。

    图 12:选择 Access Manager Identity Subject 作为主体类型
     
  8. 在图 13 所示的屏幕上,在 Name 字段中键入 Admin Role,因为对于 Admin 角色,此策略允许 ALL 访问 SSN 字段。在 Filter 下面,将 admin admin 添加到 Selected 区域中。单击 Finish 按钮以返回到上一屏幕。

    图 13:指定 Access Manager Identity Subject 的设置
     
     

    简要列出了刚创建的规则和主体。

    图 14:Claims Process Policy 的规则和主体
     

从 CLI 中:

  1. 创建一个名为 ClaimsApplicationPolicies.xml 的 XML 结构,它符合 DTD amAdmin.dtd 并包含策略信息。
  2. 导入 ClaimsApplicationPolicies.xml。键入以下内容,全部放在一行中:

    /opt/SUNWam/bin/amadmin --verbose --runasdn uid=amAdmin,ou=People,dc=ebhealthinsurance,dc=com --password admin-password --data ClaimsApplicationPolicies.xml

Access Manager 随后生成以下输出:

Info 107: Calling XML PARSER
Info 108: XML file to parse:ClaimsAppPolicies.xml
Info 101: Processing ClaimsAppPolicies.xml
Info 111: Requests generated by amadmin
Info 130: Created Policy under Organization dc=ebhealthinsurance,dc=com
Info 102: Done processing ClaimsAppPolicies.xml
Success 0: Successfully completed.

 

Claims 应用程序现在即可通过调用针对 Access Manager 的策略评估来保护其资源。

本部分介绍了如何在 Claims 应用程序中使用 Access Manager SDK 实现安全性。

过程简介
此过程包括在提供 Claims 应用程序的 Java EE 容器中安装 Access Manager Policy Agent(包括 Access Manager SDK)。要与 Access Manager 进行连接,Policy Agent 应设置所需的客户机 Java 归档 (JAR) 文件和配置。而此配置又允许与 Java EE 平台兼容的应用程序通过 Policy Agent 验证和基于 URL 的粗略授权对访问进行保护。

要获得额外的授权级别,则需要使用应用程序代码中的 Access Manager SDK。在策略评估过程中,Access Manager 自动在服务器端反映策略更改。

可通过编辑 AMAgent.properties 文件来配置缓存参数(大?⑵渌奔浼涓簦6杂?EB Health 而言,由于 Policy Agent 已配置了适当的缓存级别,因此,不需要使用任何自定义缓存机制。

图 15 是部署方案的概括视图。

图 15:部署

 

深入研究代码
本子部分引用了一些代码段来说明如何执行授权过程。

策略评估和策略决策
以下代码段用于评估策略:

String serviceName = "CustomClaimsApplicationPolicyService";

String resourceName = "SSN_FORM_FIELD";

com.sun.identity.policy.client.PolicyEvaluator pe;
PolicyDecision policyDecision;

Map envParams = new HashMap();

/*
Note: The implementation of PolicyEvaluator is from package com.sun.identity.policy.client
*/
pe = new PolicyEvaluator(serviceName);

policyDecision = pe.getPolicyDecision(token, resourceName, actionNames, envParams);

String str = policyDecision.tostring();
String xml = policyDecision.toXml();

 

此处,使用相应参数来调用客户机 PolicyEvaluator。根据从 Claims 应用程序中传递的参数,Access Manager 返回表示访问级别的策略决策。

PolicyDecision 对象包含以下两种方法之一:

  • toString — 此方法生成输出 permission=[all].
  • toXML— 此方法生成以下输出:

    <PolicyDecision>
    <ResponseAttributes>
    </ResponseAttributes>
    <ActionDecision timeToLive="1179344504796">
    <AttributeValuePair>
    <Attribute name="permission"/>
    <Value>all</Value>
    </AttributeValuePair>
    <Advices>
    </Advices>
    </ActionDecision>
    </PolicyDecision>
     

如果为资源配置了多个权限,Access Manager 将在评估过程中返回这些权限的列表。请考虑具有以下两个角色的用户示例:

  • AdminALL 访问 UserForm资源。
  • EmployeeCREATEREAD 访问 UserForm 资源

在评估策略后,Access Manager 在用户的 UserForm 上返回这两种方案之一:

  • toString 方法,它将生成 permission=[all, create, read]
  • toXML 方法,它将生成以下输出:

    <PolicyDecision>
    <ResponseAttributes>
    </ResponseAttributes>
    <ActionDecision timeToLive="1179346529031">
    <AttributeValuePair>
    <Attribute name="permission"/>
    <Value>all</Value>
    <Value>create</Value>
    <Value>read</Value>
    </AttributeValuePair>
    <Advices>
    </Advices>
    </ActionDecision>
    </PolicyDecision>
     

确定访问级别
您可以将 PolicyDecision 中返回的权限放在类(如 AccessLevel)中,并在运行时将其作为一个或一组对象进行管理。如何处理给定资源的一组访问级别可能因应用程序要求而异。EB Health 要求将权限作为 AccessLevel 类的结果集返回,以便于执行进一步的操作。作为一种安全措施,Claims 应用程序在授予访问权限和呈现页面之前,先在结果集中查询特定的权限。

请参见此 AuthZClientProxy,客户机代理类 (AuthZClientProxy )在其中封装 Access Manager SDK,并根据 ActionDecision 创建 AccessLevel对象。此策略通过封装特定于 Access Manager SDK 的代码来用作基本 Access Manager SDK 的外观。

另外,还可以从 Web 层中使用 HttpSerlvetRequest,或者从 EJB 层中使用 EjBContext 实例化代理客户机。这两个上下文对象都允许代理客户机检索由基本 Policy Agent 创建的 SSOToken。对于 EB Health 而言,Access Manager SDK 还对策略决策进行缓存以提高性能。有关缓存配置,请参见 Policy Agent 的配置文件。

EB Health 在 Web 组件和 EJB 组件中实现了客户机代理。此代理封装特定于 Access Manager SDK 的调用,并将抽象层发送到应用程序。基本 Policy Agent 要求使用 URL_POLICY 模式以便在 Web 层中顺畅地进行传播。

重要注意事项: 请务必设置正确的模式,以便将主体信息传播到各层中,从而正确地评估策略。否则,将会导致拒绝对应用程序进行的访问。

以下是相关的代码段:

public void doGetPost (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

AuthZClientProxy client = new AuthZClientProxy(request);
AuthZResultSet levels = client.authorize(resource);
If (levels.hasAll()) {
//User has all permission to resource
} else if (level.hasCreate()) {
//User has create permission to resource
} else if (level.hasRead()) {
//User has read only permission to resource
} else if (level.hasUpdate()) {
//User has update permission to resource
} else if (level.hasDelete()) {
//User has delete permission to resource
} else {
//User has other access level or no permission to resource
}

 

EJB 层中也包含相同的代码。唯一的差别是,必须在实例化过程中将 EJBContext 传递给构造器函数。此后,Access Manager SDK 将使用 EJBContext 检索尝试访问资源的主体身份令牌。在验证过程中,Access Manager 将创建用户令牌,并将其传播到 Web 层和 EJB 层。

以下代码段说明了这一方案:

EJBContext ctx;
AuthZClientProxy client = new AuthZClientProxy(ctx);
AuthZResultSet levels = client.authorize(resource);
If (levels.hasAll()) {
//User has all permission to resource
} else {
if (levels.hasCreate()) {
//User has create permission to resource
}
if (levels.hasRead()) {
//User has read-only permission to resource
}
if (levels.hasUpdate()) {
//User has update permission to resource
}
if (levels.hasDelete()) {
//User has delete permission to resource
}
} // else

 

重要注意事项:要在 EJB 层中实现策略评估 API,您需要将 Policy Agent 配置为 J2EE_POLICYALL 模式。否则,将会导致拒绝对应用程序进行的访问。

EB Health 例子说明了可通过 Access Manager(作为一种保护 Java EE 应用程序资源的平台)轻松自定义所需的扩展。与所有企业实现一样,EB Health 需要使用周密的架构来满足服务级别的要求。必须采取适当的措施来控制所有应用程序的策略推出过程。

此系列文章的第 2 部分通过使用批量操作进行的策略评估,来说明如何最大限度地减少发送到 Access Manager 的请求数量,以提高性能。此文章还将说明如何结合使用 Access Manager 和 Microsoft .NET 服务,以及 EB Health 如何使用 Access Manager 保护这两个平台。请密切关注后面的文章。

我们在此诚挚感谢 Bartosz Adamczyk、Rajeev Angal、Dilli Dorai、Rajeev Parekh、Pat Patterson 和 Aravindan Ranganathan,他们提供了非常宝贵的反馈意见和建议。