尽管 Web 服务器能够为应用程序执行用户身份验证和粗粒度的授权检查,但是 Web 服务和面向服务的体系结构(Service-Oriented Architecture,SOA)开发人员通常必须编写自定义代码来限制对某些系统功能的访问,或者基于用户的标识来自定义行为或外观
尽管 Web 服务器能够为应用程序执行用户身份验证和粗粒度的授权检查,但是 Web 服务和面向服务的体系结构(Service-Oriented Architecture,SOA)开发人员通常必须编写自定义代码来限制对某些系统功能的访问,或者基于用户的标识来自定义行为或外观。在应用程序中嵌入授权检查很不灵活,易于出错,并且增加了复杂性。如果授权检查是数据驱动的而不是由程序逻辑实现的,结果会怎么样呢?通过重用某个授权框架,脚本和编译后的程序可以更小、更简单、更安全,并且可以减少应用程序开发时间和工作量。
引言
您也许熟悉操作系统提供的访问控制功能。它通常对系统调用和通过文件系统指定的资源的操作请求执行授权检查。程序员通常不必测试运行程序的用户是否有权读取数据文件和设置系统时间。操作系统将负责此任务,并通过一个返回值让程序知道是允许还是拒绝此操作。例如,UNIX® 强制实施通过文件所有者 ID、组 ID 和与实际或有效用户标识相关的权限来建立的要求。尽管此设计非常简单,但它可能不够,从而导致某些类 UNIX 系统通过访问控制列表和其他机制对其进行扩展。其他操作系统则使用了更精细的安全模型。而且,该安全模型通常适用于系统已知的文件对象和用户帐户(出现在 /etc/passwd 或 NIS 中的文件对象和用户帐户中)。
对于某些基于服务器的应用程序,此模型是足够的。服务器最初使用增强的特权来执行,因此它能执行任何操作。当代表某个特定用户执行操作时,它实际上就变成了该用户。或者,服务器可以使用系统调用来构建安全模型,从而将操作限制到允许该用户执行的操作。在执行该操作前,程序必须测试授权:当前用户是否允许执行该操作?
Web 服务的授权检查
对于所负责的资源和操作系统无法识别的用户帐户,程序有时必须强制实施它们自己的访问控制要求。一个初步的示例是 Apache Web 服务器,可以配置它授予或拒绝针对其某个资源的 HTTP 请求。专用密码文件中的条目将创建 Web 服务器帐户,这些帐户完全独立于操作系统已知的帐户。同样,专门创建了供 Web 服务器使用的组成员资格列表。Apache 管理员可以将这些名称与服务器的 Require、Allow 和 Deny 指令一起用于描述谁能够(或不能)访问某个资源。由于操作系统在这方面帮不上什么忙,所以 Apache 程序员实现了他们自己的授权子系统。
尽管可以统一 Web 服务器和操作系统的用户列表,但通常出于安全性、性能和实现目的考虑而将它们保持分离。
诸如 Apache 等 Web 服务器提供的授权类型可以称为粗粒度 访问控制,因为它只提供了一个外部安全层。授权检查的结果将确定是否应该允许该请求。如果对某个 Web 服务的访问被拒绝,例如该 Web 服务不是由该 Web 服务器执行,则该 Web 服务甚至从来不会看到该请求。
然而,许多基于服务器的应用程序(包括基于 Web 的应用程序)所需的授权测试功能远远超出了此范畴。请考虑这样一个 Web 服务应用程序,它可由任何人执行,但是对不同的用户授予不同的能力和权限。也许最简单的示例就是其中仅允许某些用户能够访问管理功能的应用程序——所有其他用户不仅无法执行这些功能,他们甚至不应该能够看到这些功能(这些功能不应该在菜单上列出,或者至少是不可选择的)。另一个常见示例是应用程序的每个用户都有各自的配置文件,这些配置文件只能由其所有者(也许还包括应用程序的管理员)修改。通常,应用程序必须限制特定用户对其数据的访问。此类授权测试可以称为细粒度 访问控制,因为运行应用程序将其应用于该程序所使用的几乎任何类型的资源。
在某些情况下,有点创造力的程序员可能应用某些小伎俩来绕过这些问题。例如,应用程序可能使用 URI 来指定其资源,配置这些 URI 的 Web 服务器访问控制,然后发出 HTTP 请求来确定某个用户受否获得授权。此方法将利用 Web 服务器的授权检查机制,但是并不实用。
大多数编程语言(包括 Perl)在这方面都无计可施。它们在基础系统所提供的安全性之上提供一个简单的安全层。Java™ 语言包括一个授权框架,但是对 Perl 或 C/C++ 程序员来说当然没有任何帮助。
程序员面对的挑战是双重的:首先,这些应用程序的用户不需要在基础系统上拥有帐户;其次,对象的类型和访问对象的方式可能与操作系统安全模型所旨在处理的内容差别相当大。结果,程序员被迫编写大量的代码来支持特定于应用程序的授权测试,有时还必须以不同的语言重新实现本质上相同的框架。诸如 Oracle 和 MySQL 等数据库系统管理它们自己的用户帐户、角色和系统及对象级别的操作权限。
细粒度授权检查
细粒度访问控制不只是授予或拒绝执行程序或读取数据文件的权限。请考虑一个实现为 CGI 程序的 Wiki 服务器。它维护一个网页集合,每个用户一个网页。任何人都拥有对任何网页的读取访问权限。任何用户都能添加或管理他们自己的网页内容,但是不能添加或管理其他用户的网页内容。指派为管理员的任何用户都能更新和管理任何页面(例如,删除攻击性或非法内容)。在向所有者或管理员显示网页时,所有操作都应该可以通过菜单或链接来选择;其他用户不应该看到这些操作,或者这些操作对他们应该是不可选择的。此外,应用程序必须确保任何人都能看到某个网页,但是只有其所有者或管理员才能执行受限制的操作,例如更新页面的内容。