级别: 中级

Paul Ilechko (paul.ilechko@us.ibm.com), 高级解决方案架构师, IBM
Mannie Kagan (kagan@ca.ibm.com), WebSphere IT 专家, IBM

2006 年 9 月 25 日

授权体系结构可能非常不合理,存在大量问题。在本文中,您将了解如何调整应用程序的开发工作,以有效地使用 IBM® WebSphere® Application Server 中的授权功能。

引言

在安全方面,身份验证和隐私已基本标准化和产品化。而对于授权,每个应用程序通常都有自己独特的方式,这取决于相关应用程序的具体特征。虽然这样说,但在许多应用程序中,重复使用某些模式也非常常见,在如何有效利用 IBM WebSphere Application Server(及其他应用服务器)提供的各项功能方面,存在着一些最佳实践(尽管内置授权功能并不能完全满足特定场景的业务需求)。

本文总结了一些基本授权模式和 J2EE™ 领域内授权技术的发展情况,并提出了一种常用方法,以解决一般情况下的授权问题。其中的大部分信息都是与产品无关的,不过我们将在合适的时候讨论 WebSphere Application Server 的具体功能。





回页首


什么是授权?

授权就是基于用户的权限或用户的类别(在这种情况下,“用户”可能指某个外部系统,而不一定是个人)管理对受保护系统资源的访问。因此,授权假定已进行了身份验证,因为如果不知道用户是谁,则根本无法提供恰当的访问控制——而不是在通常情况下所有用户都具有相同的权限。稍后我们将详细说明各种授权模式或方式,但首先我们将对其做一个简要的总结。

  • 基于角色的授权

    基于角色的授权基于用户是某类用户的成员这一事实提供对资源的访问。这通常依赖于用户具有在用户注册中心定义的组标识。此方法定义受保护系统的各个组件,并将这些组件映射到能够对其进行访问的用户组。这种类型的授权是 J2EE 领域的标准模式。总的说来,这是一种非常粗粒度的安全形式,用于处理对系统的功能领域的访问,可以由 URL 或对 EJB 组件的方法调用进行定义。这并不是说无法使用角色定义更细粒度的保护,但这样做的效果通常不好。

  • 基于实例的授权

    与 J2EE 基于角色的授权通常提供的授权相比,此模式提供了更细粒度的授权,可以一直细化到项目内的单个对象的级别。我们现在讨论的是数据保护,而不只是功能保护。

  • 基于关系/所有权的授权

    这种类型的授权是基于实例的模式的一个特例,在基于实例的模式中,在应用程序的数据结构内存在用户与某些其他受保护的数据之间的所有权关系。这通常意味着必须将授权规则嵌入到应用程序本身的数据访问逻辑之中。

  • 用户界面自定义

    虽然这不是真正的授权类型,但与此紧密相关的一个问题是对用户界面进行自定义,以使其仅显示允许特定用户看到的特定功能。例如,菜单或门户页将不会显示未授权用户访问的链接或 Portlet。这实际上是一种预先授权;授权询问“我能这样做吗?”,而预先授权则询问一个略为不同的问题“如果我询问是否能进行此操作,答案会是什么?”不过,正如我们稍后将看到的,这两种情况下的编码技术可以完全相同。

J2EE 基于角色的授权

基于角色的授权通过仅将资源提供给已分配相应角色的用户来保护资源。J2EE 提供了通过使用声明和编程技术来完成此任务的标准方法。我们稍后将在授权技术部分中详细讨论 J2EE 安全性。不过,务必理解 J2EE 领域中的角色概念。关键要记住,J2EE 角色不是一组人员。它们是特定于应用程序的逻辑名称,可以在部署时映射到用户和组。角色本身通常表示 J2EE 应用程序中的权限集合。

实际定义哪些用户属于哪些组是在用户注册中心中进行管理的。这可以是企业 LDAP 服务器,也可以是仅由单个应用程序使用的数据库,但用户和组信息的存储库位于 J2EE 环境之外。在 J2EE 应用程序内,您可以基于这些角色定义和命名安全角色及约束资源访问。因此,角色是权限集合;为了使用它,必须在部署应用程序时将其绑定到某一组用户。可以按名称将其映射到一个或多个用户,也可以映射到一个或多个用户组,还可以映射到二者的任意组合。术语主体通常是指用户或用户组。

您将看到,虽然 J2EE 角色可能通过简单的一对一映射紧密地映射到注册中心组,但并不一定非得如此;在最简单的情况下,可以将“manager”角色映射到称为“manager”的组,但 J2EE 角色的强大之处在于,它提供了出色的灵活性,能够在组织发生更改时更改绑定,而无需进行编程更改。以下列情况为例,假定特定的应用程序功能仅对法律部门的员工可用,而这些员工都属于 Department 102。可以在应用程序中创建一个名为“legal”的 J2EE 角色,并绑定到注册中心组“Dept102”。如果以后对该部门进行了重组,其中一半的员工转到了 Department 507,则可以更改绑定,以映射到“Dept102”和“Dept507”。然后,当属于这两个部门的任何员工经过了系统的身份验证后,就会向其授予“legal”角色,系统会向其提供恰当的访问权限。

自定义基于角色的授权

即使使用编程 API,仍然会有因 J2EE 角色模型不够灵活而难以满足业务需求的情况。不过,在草率行事前,应该对以 J2EE 模型为基础(而不是将其替换)进行构建的可能性进行分析。这样做的优势包括:

另外要注意,有时候,可以通过应用服务器安全运行时的其他可插入功能来获得所需的灵活性。例如,如果需要角色-组映射在运行时具有动态性(根据用户登录时提供的信息),则可以使用 JAAS 登录扩展来满足此需求(请参见 Advanced authentication in WebSphere Application Server)。在 WebSphere Application Server V5.1.1 或更高版本中,可以在 Trust Association Interceptor 或 JAAS 登录模块中创建动态组成员身份。不过,如果角色与上下文相关(基于具体的应用程序使用情况),则可能需要购买或构建授权框架。医疗应用程序就是上下文使用模式的一个例子:医生可以一次性登录到系统,但根据所查看的病人或医疗实体(如医院或诊所)的上下文的不同,该医生的角色可能会从检查医师更改为主治医师。此更改是在会话过程中动态更改的,而不仅限于进行身份验证时可用的信息。

只要认为 J2EE 应用程序授权本身不足以解决您的问题,下一个问题就是要确定是否构建或购买授权解决方案。IBM Tivoli® Access Manager 等企业安全产品提供了灵活的、基于策略的功能授权。不过,将这些功能与应用服务器相集成可能有一定的挑战性。您需要考虑的一些问题包括:

  • 是否使用专用 API?
  • 将提供何种功能?
  • 授权请求外部化会带来何种性能损失?

Java™ Authorization Contract for Containers (JACC) 是一种基于标准的方法,用于将外部安全管理器与应用服务器集成。JACC 提供了将安全授权的权限检查委托给外部提供程序的功能。由于授权检查是在容器将控制权交给应用程序前进行的,因此 JACC 具有能够清楚区分自定义授权逻辑和应用程序逻辑的优势,从而满足了关注点分离的需求。不过,使用 JACC 时有一些方面需要特别注意,因此有必要更深入地探讨 JACC,以准确了解其执行的工作以及可对其加以应用的场合。我们稍后将对 JACC 进行更为详细的讨论。

基于实例的授权

顾名思义,基于实例的授权就是将访问权限授予某个对象的特定实例。基于实例的授权通常使用访问控制列表(Access Control List,ACL)来保护实例,而 ACL 存储在某种类型的策略存储区中,并且可用来制定访问决策。可以将 J2EE 角色作为 ACL 使用,不过这个方法可能会不方便。正如我们前面所讨论的,J2EE 角色终究只是一个名称,是可以绑定到任何一组主体的逻辑构造。这种方法不能很好地扩展来大量使用 ACL,也不能处理在应用程序执行时动态修改 ACL 的情况;因为我们曾提到,部署描述符在应用程序启动时以静态方式定义 J2EE 角色。考虑到这些限制,在许多情况下,更好的方法可能是使用外部安全解决方案或 ACL 基于实例的安全性自定义框架。

为了更便于理解,让我们看一个例子。假定我们有一个新的 J2EE 人力资源系统,可允许用户执行打印相关的任务,如将文档发送到打印机和查看与管理打印队列。由于可打印数据的敏感特征,需要进行某些限制。例如,可能存在有关授权哪些用户使用或管理哪些打印机的规则。还可能存在有关在每天的特定时段使用打印机的规则;或许会考虑连夜在特定的打印机上打印敏感材料。

我们可以使用标准的 J2EE 基于角色的安全性来管理打印机访问。例如,可以为打印机和所需访问类型的每种组合定义一个角色,最终得到“Allowed_to_print_to_PrinterX”或“Allowed_to_manage_queue_for_PrinterY”之类的角色。然后,我们必须在应用程序中编写代码,以使用 isUserInRole() 调用遍历所有可能的角色,从而验证当前用户是否被授权执行他们所尝试的任何打印相关操作,而且我们必须将每个角色绑定到相应的用户注册中心条目。

正如您所看到的,这并不是授权需求的一个条理非常清楚的实现。添加任何新打印机都会要求对应用程序进行更改;而有关何人可以进行何种操作的规则的变化则会要求重新将这些角色绑定到主体,并重新部署应用程序。此外,我们尚未开始考虑时段问题。我们需要能够存储与每台打印机对应的可配置信息,但在标准 J2EE 授权模式中,实际上却没有任何地方能够放置此类信息。

现在,如果我们要使用独立的授权服务,这可以极大地简化解决方案,因为我们将只需要询问授权服务,当前用户是否可以对某个对象执行某项操作。所有这些都将外部化,从而极大地简化了编程模型,并使得对外部提供程序的更改以实时的方式反映到正在运行的应用程序中。我们稍后将再次对此问题进行讨论。

所有权关系

直接所有权是用户和某些受保护数据间的一种十分常见的基于实例的关系。例如,在经纪业应用程序中,理财顾问可以查看其个人客户的帐户,但却不能查看公司的其他客户的帐户。部门经理可以查看所属的理财顾问的所有客户的所有帐户,但却不能查看其他部门的客户的帐户,诸如此类。在这种情况下,权限内置到应用程序的数据结构中。

应用程序很少会采用以下这种方式,即向用户界面提供用于检索所有数据的帐户列表,然后再向每一行应用基于 ACL 的权限。这里存在的主要问题是性能:与在 Java 代码中进行筛选相比,在数据库引擎中进行行筛选通常要快得多。尽管缓存可能在一定程度上减轻这种性能影响,但如果使用特定大小的数据块检索数据来支持用户界面分页,则可能出现另一个问题。如果筛选在应用程序中进行,则无法知道请求了多少行,因此可能导致通过多次调用来获取单页数据的情况。

遗憾的是,尽管存在种种缺陷,这种应用程序端筛选方法却被经常使用。如果应用程序使用对象关系映射工具来执行数据访问,然后尝试以某种通用方式将安全机制应用到实例化的类,则尤其可能出现问题。这是对计算资源的一种极为低效的使用,获得可接受的性能和可伸缩性的可能性非常小。

唯一合理的方法是让数据库进行筛选。如果数据库知道最终用户的标识,或通过修改对实际数据访问逻辑的筛选将授权逻辑嵌入到应用程序中(通常通过将相应的项目添加到 SQL 语句的 Where 子句中),则可以通过利用本机数据库授权来实现此目的。取决于应用程序复杂性,或许可以开发一个使用元数据描述授权规则的自定义框架,以自动将安全更改应用到 SQL。如果将存储过程用于数据访问,则这些存储过程也是应用这些规则的最佳场所。

用户界面自定义

动态修改用户界面,以仅向用户显示其能够执行的操作,这样的做法常常也被视为授权的一个方面。虽然这很有争议,但它无疑是一个常见的问题;向用户显示他们未被授权执行的链接的做法肯定非常不好(并可能招致黑客攻击)。

自定义 UI 以删除链接和菜单选项的做法与基于角色的授权非常相似。这通常只是简单地使用 isUserInRole() 调用来遍历各项,从而验证用户是否应该看到此项。还可以采用相同的方式自定义表单上的实际数据,不过这可能会导致进行冗长烦琐的编程,而且不能提供足够的灵活性,具体取决于业务需求。当需要将访问控制自定义与其他类型(如用户首选项)集成时,这种方法可能会变得尤为复杂。如果用户能够访问允许开发自己的特定 UI 组件视图的某种首选项工具,则该工具也需要识别授权规则元数据,以防止用户向其个性化表单添加其不应该具有访问权限的项。正如前面讨论自定义基于角色的授权时所提到的,可能会存在数据视图与上下文相关的情况,并不能仅简单地基于静态角色对其进行调整。





回页首


授权技术

J2EE 同时提供了声明和编程形式的基于角色的授权功能。尽管本文并不打算作为 J2EE 安全方面的教程,但我们将对其主要方面进行简单的总结。

J2EE 声明形式的授权

可将 J2EE 安全角色和约束添加到应用程序的部署描述符。Web 约束添加到 web.xml 中,它们是基于 URL 模式的。EJB 约束添加到 ejb-jar.xml 中,用于定义方法级别的权限。WebSphere Application Server 提供了相应的工具,允许部署人员定义哪些用户和组(按照用户注册中心中的定义)有权访问哪些安全角色。应用服务器运行时使用这些绑定来确定是否向特定的用户授予了某个角色,然后决定是否可访问受保护的资源。

J2EE 编程形式的授权

声明形式的授权简单而强大,但经常并不能提供足够的控制。一旦对用户界面自定义的问题进行分析后,此问题则会变得更为明显。为了提供额外的灵活性,J2EE 提供了 API,以允许开发人员使用下列调用来测试当前用户是否具有访问特定角色的权限:

  • 对于 Servlet 使用 isUserInRole()
  • 对于 EJB 使用 isCallerInRole()

此外,还有用于提供对用户标识的访问的 API 调用:

  • 对于 Servlet 使用 getUserPrincipal()
  • 对于 EJB 使用 getCallerPrincipal()

通过使用这些 API,您可以开发任意复杂的授权模型。在极端的情况下,如果 J2EE 角色信息没有用处,则可以获取用户标识信息,并使用其查找和执行存储在某个其他来源(如数据库或规则引擎)中任意复杂的授权规则。

任何针对以后的 API 编写的代码都可能存在移植性问题,因为 Principal 对象的格式并未标准化,在不同的应用服务器平台上可能会有所不同。

JACC

正如前面所提到的,JACC 提供了一种标准方法来将外部授权提供程序插入到 J2EE 容器中。这样,第三方授权提供程序就能够在用户访问 J2EE 资源时进行授权决策了。

在 JACC 之前,并没有针对应用服务器作出的访问决策的规范。在没有 JACC 的情况下,要使用供应商实现和专用接口进行第三方供应商产品集成。当时并没有标准方法可以使第三方授权提供程序(如 Tivoli Access Manager)插入应用服务器以作出访问决策。为了解决这些问题,Sun Microsystems™ 在 J2EE 1.4 规范中引入了 JACC,从而提供了一项标准机制,以供第三方提供程序从应用程序和应用服务器收集安全策略信息并在运行时实现策略决策。

这些运行时策略决策是通过 java.security.Policy 类作出的。在方法预分派阶段,Web 和 EJB 容器会通过调用 Java Security Manager checkPermission 方法来在运行时执行安全策略;Java Security Manager checkPermission 方法会委托给抽象类中的 implies 方法。JACC 提供程序必须提供实现 implies 方法的具体 Policy 子类。此外,JACC 提供程序还必须实现 PolicyConfiguration 接口,并提供具体 PolicyConfigurationFactory 类。

在部署应用程序时,策略配置权限对象会将自身添加到提供程序中。它们包含容器中配置的与 Web 和 EJB 安全相关的 J2EE 部署描述符信息。这是容器用于将安全策略信息传递给提供程序的机制。

在运行时,如果用户访问 Web 或 EJB 资源,容器将创建相应的 Web 或 EJB 权限对象,并调用提供程序的 Policy 对象的 implies 方法。permission 对象包含有关所访问的资源的信息:如果资源是 Web 资源,则 permission 对象为 URL;如果资源为 EJB,则 permission 对象包含 EJB 对象和方法的名称。封装 Principal 的 Protection Domain 对象也有可能会传递给 Policy 对象。而且,提供程序能够通过容器注册的 PolicyContext 处理程序的 getContext 方法来访问细粒度资源属性,如 EJB 调用的特定参数。提供程序将随后通过向 Policy.implies 方法返回 True 或 False 来负责准许或拒绝对资源的访问。(有关 JACC 的更多信息,请参见 JACC API 规范。)

JACC 最初的目的是为了提供一个标准接口,以便第三方能够插入授权提供程序来作出访问决策。下面让我们看看 JACC 可能能够满足的一系列安全需求。

外部化标准 J2EE 安全模型

标准 J2EE 安全模型包含角色的描述,包括可由主体访问的受安全机制约束的资源。正如前面所提到的,JACC 提供程序可访问此信息,并全面支持这些访问决策的外部化。

扩展标准 J2EE 安全模型

标准模型是静态的。约束和角色在部署受安全保护的应用程序时确定。标准模型中并没有规定如何在部署后修改角色-约束关系。不过,JACC 提供程序并不仅限于标准 J2EE 安全模型的静态特性。JACC 提供程序还具有进行动态的基于运行时的访问决策所必需的自主性和信息。

例如,我们经常要考虑这样的问题:特定角色是否可以对特定的对象执行特定的操作?在讨论 JACC 带来的利弊前,让我们考虑如何将这种关系映射到标准 J2EE 安全性以及 JACC 使用。

标准 J2EE 可以部分地满足此映射,例如,可以将对象 映射到会话 EJB 类,将 操作 映射到特定的安全 EJB 方法。同样,正如我们前面所提到的,此映射是静态 的。

而另一方面,JACC 能够支持上述映射,而且还支持动态的基于实例 的访问控制。例如,可以通过以下方式执行授权检查:将操作参数传递给 EJB 方法调用,以允许动态确定授权检查。我们将在稍后讨论一个示例。

现在,让我们了解一下在考虑 JACC 时需要注意的一些与性能及实现复杂性相关的事项:

  • 在使用 JACC 基于方法参数的访问时可能会存在性能影响。例如,WebSphere Application Server 支持 JACC 规范所要求的所有策略上下文处理程序。不过,由于存在性能影响,除非提供程序专门要求,否则 EJB 参数策略上下文处理程序并不会激活。如果必须为每个 EJB 方法的每个参数创建对象,则会带来性能影响。

  • 实现 JACC 来支持标准 J2EE 安全性之外的功能可能是一项非常复杂的任务。JACC 为实现标准 J2EE 安全模型提供了良好的支持。例如,在 permssion 对象上提供了一些易于使用的有用方法,用于检查传入 permission 对象是否满足 J2EE 部署描述符的策略要求。 另一方面,JACC 并未提供对执行非标准权限检查的支持,而扩展 J2EE 安全模型又将需要这种支持。实现扩展 J2EE 安全模型的 JACC 提供程序是一项复杂的任务,不应轻视。

  • JACC 配置应用于整个计算单元内。任何 JACC 提供程序都必须满足计算单元内的所有应用程序的授权要求。对于其中一些具有标准 J2EE 特征,而一些又有特殊要求的情况,则必须提供同时满足这两组要求的提供程序——而这就增加了复杂性。

现在让我们简单了解一下如何使用 JACC 处理我们的打印机授权问题。我们可以使用具有以下类似方法的“Printer”会话 Facade EJB:

  • print(printerName:string, itemToPrint:string)
  • manageQueue(printerName:string, queueOperation: string)

在我们的 JACC 提供程序内部,可以提供一个 EJB、角色、操作和对象的映射表;例如,通过使用“Printer”EJB,“Managers”能够对“PrinterX”执行“ManageQueue”操作。

能够采用可选的方式使用 J2EE 授权约束对 Facade EJB 方法进行保护。不过,无论是否提供安全保护,都将调用 JACC 提供程序的 Policy.implies 方法。在提供程序内部,一旦完成了常规 J2EE 授权检查,我们就会检查 EJB 是否为映射中使用的 EJB 之一,然后根据我们的映射表来检查 EJB 参数。如果调用已授权,则将从 Policy.implies 方法返回 True。

顺便提一下,在我们的 JACC 提供程序内部,由于我们是在用户的调用线程上进行执行,因此可以通过针对表中的角色(例如,“Managers”)调用常规 J2EE isCallerInRole 方法来检查调用主体是否属于相应角色。

企业安全产品

正如我们前面所讨论的,Tivoli Access Manager 之类的企业安全产品通常设计用于解决一系列授权问题。要实现这个目的,可以采用两种方法,第一种方法是将授权规则从应用程序外部化,并提供 API 来调用授权规则引擎,第二种方法是通过使用 JACC 接口插入 J2EE 容器来透明地调用授权规则引擎,另外,还可以同时使用这两种方法。当产品同时提供 JACC 和基于专用 API 的解决方案时,务必了解每个模型中可用的功能。例如,对于 Tivoli Access Manager,JACC 并没有提供太多的附加值,因为它实际上仅提供了 J2EE 安全检查的委托功能,但却无法将关于访问控制检查的对象的其他信息(如参数)传递给方法调用。在这种情况下,API 方法的功能要丰富得多,但要在可移植性和功能之间进行折衷。

现在让我们回头看看如何使用 Tivoli Access Manager 解决我们的打印机授权问题。

Tivoli Access Manager 提供了定义受保护对象空间和向对象层中任何位置的对象添加 ACL 的功能。在我们的示例中,我们可以为希望保护的打印机定义一个树形结构。ACL 具有与其关联的特定缺省操作(或权限),但如有必要,可以创建自定义操作组。对于我们的场景,可能会随后决定创建一个名为“print_actions”的操作组,并在其上定义专门用于控制打印的权限位,如“q”表示加入打印机的打印队列,“p”表示打印,“v”表示查看打印队列,“d”表示从队列中删除,等等。我们可以随后在对象空间中恰当的位置添加 ACL,并将用户或组添加到这些 ACL 中,以定义可用权限。添加到 ACL 的每个用户或组可以具有不同的活动权限,从而可对任何用户可用的访问权限类型进行适当的细粒度控制。如有必要,我们还可以向任何对象添加受保护对象策略(Protected Object Policy,POP),从而提供额外的保护,如时段访问规则等。

完成了此配置后,剩下的工作就是添加一个简单的 API 来调用应用程序了。这将使用 aznAPI,以便询问 Tivoli Access Manager 是否允许进行某项操作。在此调用中,我们将传递用户凭据、受保护资源的标识,以及所请求的操作,然后 Tivoli Access Manager 将对该对象上的 ACL 和 POP 进行计算,并返回一个 Boolean 值。正如您所看到的,与尝试对基于角色的安全模型进行修改来适应其设计时并未考虑的情况相比,这显然是更为灵活的解决方案。

展望:SAML 和 XACML

尝试确定任何技术将来的发展方向是一件风险很大的事,但安全性断言标记语言(Security Assertion Markup Language,SAML)和可扩展访问控制标记语言(eXtensible Access Control Markup Language,XACML)极有可能成为未来安全策略实现的重要方面。尽管本文并不打算详细描述这些技术,但这里将进行简要的总结,并概括说明在 J2EE 授权领域中这些技术之间的关系。

SAML 通常被认为是一项 Web 服务标准,不过事实上,它却提供了独立于平台和协议的联合标识的总体管理结构。SAML 引入了策略决策点(Policy Decision Point,PDP)和策略执行点(Policy Enforcement Point,PEP)的概念。顾名思义,PEP 是安全体系结构中基于 PDP 中定义的策略执行身份验证和授权规则的位置。XACML 构建于 SAML 之上,提供了用于定义访问控制和授权请求及响应消息的实际语义。SAML 和 XACML 都没有提供用于交付和管理安全服务的基础设施;需由企业安全供应商提供此基础设施。

因此,所面临的问题是:这将如何影响 J2EE 应用服务器的安全性,特别是它如何影响在此领域内的授权?正如我们前面所讨论的,J2EE 应用程序中的授权功能以两种形式提供:应用服务器本身的嵌入式安全引擎和使用 JACC 接口将授权委托给外部提供程序的功能。虽然 J2EE 应用服务器供应商可以在内部使用 XACML 来定义通过应用 J2EE 安全约束创建的授权策略,但这通常是一种貌似神秘的做法,其意义并不大。而更重要的是企业安全解决方案供应商可能支持 XACML——特别是支持请求-响应协议。为了使用目前的 JACC 接口,您需要安装安全服务供应商的特定提供程序,因为并未定义从提供程序到服务的协议。通过使用定义了该协议的 XACML,可以(至少理论上如此)获得能够与任何识别 XACML 的服务进行通信的通用提供程序。





回页首


授权层次

在结束本文之前,我们还需要讨论最后一个问题。在分层应用程序(J2EE 应用程序通常属于此类)中,需要在所有层次执行授权——尤其是在最底层,这一点非常重要。例如,如果用户从浏览器发出了访问 Serlvet 的 URL 请求,而 Servlet 又调用 EJB,则在许多情况下,授权都仅发生在 Servlet 层——或者更糟糕,仅在浏览器内的 JavaScript 代码中进行授权。这可能导致系统不安全,因为黑客可以编写代码来直接调用 EJB,而得以绕过 Web 层。类似地,如果 EJB 受到保护,但数据库没有受到保护,则黑客完全可以绕过应用程序,直接进入核心地带操纵公司的数据。务必考虑系统的每个层次的可能访问路径,同时还要考虑授权如何与其他安全功能(如网络级别的保护)集成。





回页首


结束语

本文说明了 J2EE 应用程序授权中涉及的一些问题,并介绍了 WebSphere Application Server 和其他 J2EE 应用服务器的一些现有标准功能。尽可能使用现有标准将最为有利。虽然现有标准并未提供完整的解决方案,但更为明智的方法是尽可能地对其加以利用,并随后扩展其功能,而不要使用自定义解决方案完全将其替换。授权是一个复杂而颇有难度的主题,因此要慎重地考虑各方面的问题。





回页首


致谢

作者非常感谢 Keys Botzum,在提出本文包含的许多原创想法的过程中,他给予了大量的帮助,而在我们完善本文时他也多次对稿件进行了审阅。



 

参考资料



 

作者简介

 

Paul Ilechko 是 IBM WebSphere 软件服务部的一名高级解决方案架构师。Ilechko 先生拥有 25 年的 IT 行业经验,具有大型机和分布式技术背景。他从 WebSphere 和 J2EE 技术的起始阶段就开始从事这些技术工作。他的主要目标是帮助 IBM 的客户成功地使用这些产品。Ilechko 先生拥有伦敦大学的数学学士学位。


 

Mannie Kagan 是位于加拿大多伦多的 IBM WebSphere 软件服务部 (ISSW) 的一名认证 IT 咨询专家。Mannie 提供与 SOA、WebSphere 中间件、性能管理和安全性相关的咨询服务、技能培训和辅导。您可以通过 kagan@ca.ibm.com 与 Mannie 联系。