|
几年来,人们对使用可靠解决方案以保护 Web 应用程序安全的需求不断增长。为确保足够安全,大多数提供在线 Web 服务的企业在以下两个服务级别实现了安全性:
-
验证 — 确保您就是所声称的人。
-
授权 — 确认您对要访问的资源具有相应的权限。
要满足服务级别要求,您需要进行详细周密的体系结构设计,并完成大量的实现工作。
本文是系列文章的第一部分,介绍如何使用 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),
而无需修改源代码或配置。
目录
所有 EB Health 应用程序均采用两层安全模型:Web 层和 Enterprise JavaBeans (EJB) 层。
授权模型采用基于角色的访问控制 (Role-Based Access Control, 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。<
/p>
Access Manager 管理控制台 (amconsole) 是一个基于 Web 的界面,用于定义和管理资源策略。本部分介绍了如何在管理控制台或命令行界面 (Command-Line Interface,
CLI) 中配置设置,以满足这三个授权要求。
通过采用上一部分中介绍的体系结构,您可以直接配置前两个要求:
- 所有经过验证的用户进行的访问
- 基于角色对应用程序 URI 进行的访问
以下是此过程的概要步骤:
- 在托管应用程序的应用服务器上安装 Policy Agent 并启用
URL_POLICY 模式。
- 创建一个策略规则,以允许所有主体(即,经过验证的用户)访问某个 URL,例如
http://www.ebhealthinsurance.com/claims/*。
- 对于第二个要求,重复执行步骤 1 和 2。此处的主体是有权访问所定义的资源的角色。
为经过验证的用户授予访问权限
要确保能够在 EB Health 中访问 Claims 应用程序,请按如下方式定义策略、规则和主体:
- 在管理控制台中,单击 New Policy(新建策略)以创建策略,然后单击 New Rule(新建规则)以创建规则。
- 在图 2 所示的屏幕上,选择 URL Policy Agent (with resource name)(URL 策略代理(带有资源名称))。单击 Next(下一步)。
图 2:选择 URL Policy Agent(URL 策略代理)作为规则的服务类型
|
- 在图 3 所示的屏幕上:
- 在 Name(名称)字段中键入
Claims Processing Application。
- 在 Resource Name(资源名称)字段中键入 Claims 应用程序的 URL
http://www.ebhealthinsurance.com/claims/*。
- 为 Actions(操作)下面的
GET 和
POST 选择 Allow(允许)。单击 Finish(完成)。
图 3:定义规则细节
|
- 创建另一个主体,然后在图 4 所示的屏幕上选择 Authenticated Users(经过验证的用户)。单击 Next(下一步)。
图 4:选择 Authenticated Users(经过验证的用户)作为主体类型
|
- 在图 5 所示的屏幕上,在 Name(名称)字段中键入
All Authenticated Users。单击 Finish(完成)。
图 5:指定主体名称
|
Access Manager 随后确认策略设置,如图 6 所示。
图 6:确认策略设置
|
为应用程序 URI 授予访问权限
要满足第二个要求并仅为某些角色授予访问权限,请重复上一部分中的步骤 1 至步骤 3,然后执行以下操作:
- 在图 7 所示的屏幕上,选择 Access Manager Identity Subject(Access Manager 身份主体)。单击 Next(下一步)。
图 7:选择 Access Manager Identity Subject(Access Manager 标识主体)作为主体类型
|
- 在图 8 所示的屏幕上,在 Name(名称)字段中键入
Admin Role,然后从 Filter(过滤器)下拉菜单中选择 Role(角色)。
- 在 Available(可用)下面选择
admin,然后单击 Add(添加)将其移到 Selected(选定)区域中。单击 Finish(完成)。
图 8:定义主体参数
|
为应用程序组件授予基于角色的访问权限
要满足第三个要求(即,为应用程序组件授予访问权限),可通过创建一个服务来自定义 Access Manager,该服务可在较低级别(比通过 URL 资源提供的安全级别要低得多)保护组件。<
/p>
安全要求
EB Health 旨在以编程方式完成以下操作:
- 仅允许某些角色访问 Claims 应用程序中的某些部分。
- 拒绝未经授权的角色访问 Claims 应用程序中的某些部分。
- 集中收集策略存储中的信息。
为了完成这一目标,EB Health 必须保护页面级别的资源,并为每个资源指定角色的访问级别。访问级别包括
CREATE、
READ、
UPDATE、
DELETE、
ALL 和
NONE。
例如,EB Health 希望根据角色来控制对其 Claims 应用程序中的 User Profile(用户配置文件)屏幕的访问。由于有了 Java EE 应用程序,该
屏幕可以为不同的角色呈现不同的内容;这种应用程序允许用户访问资源,但限制用户可查看的内容和执行的操作(根据用户角色)。
以下两个角色可以访问 User Profile(用户配置文件)屏幕:
Admin 和
Employee。下面给出了安全要求和相关 UI,如图 9 所示:
-
Admin
— 此角色具有整个屏幕的所有权限,其中包括 SSN [社会保险号码] 字段 (SSN_FORM_FIELD)。相应地,在
Admin 进行访问时,User Profile(用户配置文件)屏幕显示可编辑的所有字段值以及 Create(创建)、Update(更新)、Delete(删除)和
Cancel(取消)按钮。
-
Employee
— 此角色具有 User Id(用户 ID)、Email(电子邮件)和 Phone(电话)字段的
UPDATE 权限,但仅具有 SSN 字段的
READ 权限。在
Employee 进行访问时,User Profile(用户配置文件)屏幕只显示可编辑的 User Id(用户 ID)、Email(电子邮件)和 Phone(电话)字段,而
灰显 SSN 字段以表明该角色具有
READ ONLY 访问权限。
图 9:根据
Admin 和
Employee 角色划分的 User Profile(用户配置文件)屏幕访问权限
|
过程
首先,扩展 Access Manager 服务并创建一个名为
CustomClaimsAppPolicyService 的服务:
- 创建一个名为
CustomClaimsAppPolicyService.xml
的 XML 架构,它符合文档类型定义 (Document Type Definition, DTD)
sms.dtd,并指定六个访问级别。
此架构还描述了服务名称、服务属性及属性值。
- 在 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.
|
注:无需重新启动服务器,即可使这些更改生效。
- 将
CustomClaimsAppPolicyService.xml 复制到 Access Manager 的本地目录中,例如
/opt/SUNWam/locale。
接下来,从管理控制台
或 CLI 中创建策略。下面的过程说明了如何创建 Claims Process Policy,并通过两种方法指定相关规则和主体。
注:对于包含很多策略规则的大型应用程序部署来说,CLI 可能更适合一些。
从管理控制台中:
- 单击 New Policy(新建策略)以创建策略。
- 使用所选的值填充 Policy Name(策略名称)和 Description(描述)字段。
- 单击 Rules(规则)下面的 New(新建)。
Access Manager 将在缺省服务类型中显示新的自定义策略服务。
- 在图 10 所示的屏幕上,选择
CustomClimsApplicationPolicyService (with resource name)(
CustomClimsApplicationPolicyService(带有资源名称)),然后单击 Next(下一步)。
图 10:选择
CustomClaimsApplicationPolicyService 作为规则的服务类型
|
- 在图 11 所示的屏幕上,定义将资源与其访问级别相关联的规则,如图中所填充的内容一样。
图 11:定义新规则的设置
|
资源名称可以是组件、小部件、页面、URL 或需要授权的任何其他对象的字符串表示形式,以提高灵活性和简便性。
- 使用以下设置为用户表单创建另一个规则:
|
Service Type(服务类型) |
CustomClaimsApplicationPolicyService
|
|
Name(名称) |
UserForm_A1
|
|
Resource Name(资源名称) |
UserForm
|
|
Choose Permission(选择权限) |
ALL
|
- 在图 12 所示的屏幕上选择 Access Manager Identity Subject(Access Manager 标识主体)为规则分配主体(角色),此处为 Access
Manager 角色。然后,按角色进行搜索以列出完整的可用角色集合。
图 12:选择 Access Manager Identity Subject(Access Manager 标识主体)作为主体类型
|
- 在图 13 所示的屏幕上,在 Name(名称)字段中键入
Admin Role,因为此策略允许
Admin 角色对 SSN 字段具有
ALL 访问权限。在 Filter(过滤器)下面,将
admin 添加到 Selected(选定)区域中。单击 Finish(完成)以返回到上一屏幕。
图 13:指定 Access Manager Identity Subject(Access Manager 标识主体)的设置
|
图 14 简要列出了刚创建的规则和主体。
图 14:Claims Process Policy 的规则和主体
|
从 CLI 中:
- 创建一个名为
ClaimsApplicationPolicies.xml
的 XML 架构,它符合 DTD
amAdmin.dtd 并包含策略信息。
- 导入
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 文件来配置高速缓存参数(大小、其他时间间隔)。对于 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 将在评估过程中返回这些权限的列表。请考虑具有以下两个角色的用户示例:
-
Admin
— 具有资源
UserForm 的
ALL 访问权限
-
Employee
— 具有资源
UserForm 的
CREATE 和
READ 访问权限
在评估策略后,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 实例化代理客户端。这两个上下文对象都允许代理客户端检索
SSOToken,后者是由基本 Policy Agent 创建的。对于 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_POLICY 或
ALL 模式。否则,将会导致拒绝对应用程序进行的访问。
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,他们提供了非常宝贵的反馈意见和建议。
- Sun Java System Access Manager
- 相关的出版物
-
- Sun 开发者服务
|