构建安全的 Web 服务

来源:百度文库 编辑:神马文学网 时间:2024/04/27 21:38:17

构建安全的 Web 服务

发布日期: 12/28/2004 | 更新日期: 12/28/2004

查看全部的安全性指导主题

Microsoft Corporation

本单元概要

越来越多的公司和单位开始创建和部署 Web 服务。然而,这通常是在并没有完全了解 Web 服务安全问题的情况下进行的。本单元阐述如何安全地设计、配置和部署 Web 服务。对于任何需要接受外部请求的应用程序,输入验证是非常重要的,本单元举出了一些技术确保只接受格式正确的请求。本单元还详细解释了可以用来限制授权用户对 Web 服务访问权限、以及确保可对用户操作进行日志记录和审核的不同身份验证方法。

本单元还讨论了 Microsoft 的 Web 服务s Enhancements 1.0 for Microsoft® .NET (WSE),它支持 WS-Security(Web 服务安全)标准和相关的一系列新出现的标准。

返回页首

目标

通过本单元可以:

设计和部署安全的 Web 服务。

使用强类型参数和 XSD 架构验证 Web 服务的输入。

对 Web 服务客户端进行身份验证。

对访问 Web 服务进行授权。

保护 Web 服务消息的保密性和完整性。

根据部署环境(Intranet、Extranet 和 Internet)选择要实现的安全选项。

了解 Web 服务s Enhancements 1.0 for Microsoft .NET (WSE)。

了解如何使用代码访问安全保护 .NET Framework 使用方代码。

懂得可以应用哪些对策应对常见的 Web 服务威胁,包括未授权访问、参数操作、网络侦听、配置数据泄漏和消息重放。

返回页首

适用范围

本单元适用于下列产品和技术:

Microsoft® Windows® Server 2000 和 Windows Server™ 2003 操作系统

Microsoft .NET Framework 1.1 和 ASP.NET 1.1

返回页首

如何使用本单元

要想充分利用本单元:

阅读“保护 ASP.NET 应用程序的安全”单元。该单元面向的是管理员,使管理员可配置 ASP.NET Web 应用程序或者 Web 服务,将不太安全的应用程序提升到安全状态。

阅读“保护应用程序服务器的安全”单元。阅读此单元,熟悉远程应用程序服务器的相关注意事项。

使用“核对表:保护 Web 服务的安全”。此核对表是对构建和配置安全 Web 服务所必需的安全措施的总结。

使用本单元理解消息级威胁,以及如何应对这些威胁

使用应用程序的类别作为解决常见问题的一种手段。以下这些部分提供了使用这些类别的相关信息。

本页内容
本单元概要 目标 适用范围 如何使用本单元 概述 威胁与对策 设计注意事项 输入验证 身份验证 授权 敏感数据 参数操作 异常管理 审核和日志记录 代理注意事项 代码访问安全注意事项 部署注意事项 小结 其他资源 返回页首

概述

越来越多的公司使用 Web 服务通过 Internet 和公司 Extranet 将自己的产品和服务展示给客户和商业伙伴。这些服务提供者的安全需求是极为重要的。在一些情况下,主要是 Intranet 或者 Extranet 场景中,可以在一定程度上控制两端的终结点,这时可使用操作系统和 Internet 信息服务 (IIS) 所提供的基于平台的安全服务提供点到点的安全解决方案。但是,Web 服务基于消息的体系结构和跨越信任边界的异构环境(Web 服务在此种环境中的使用越来越多)对我们提出了新的挑战。这些场景需要在消息级处理安全问题,以支持跨平台互用性和通过多个中间节点进行路由。

Web 服务安全 (WS-Security) 是设计用来解决这些问题的新出现的安全标准。Microsoft 已经发布了 Web 服务s Enhancements 1.0 for Microsoft .NET (WSE) ,它支持 WS-Security 以及一系列相关的新出现的标准。WSE 使您可实现消息级安全解决方案,包括身份验证、加密和数字签名。

WSE 支持的规范和标准还在发展中,因此当前的 WSE 并不能保证会与产品未来的版本兼容。在写作本单元时,使用其他供应商(包括 IBM 和 VeriSign)提供的非 Microsoft 工具集的互用性测试正在进行。

返回页首

威胁与对策

为了构建安全的 Web 服务,需要了解相关的威胁。针对 Web 服务的最大威胁主要有:

未授权访问

参数操作

网络侦听

配置数据泄漏

消息重放

图 1 显示了针对 Web 服务的最大威胁和攻击。


图 1. 主要的 Web 服务威胁

未授权访问

提供敏感或者受限信息的 Web 服务应该对其调用方进行身份验证和授权。脆弱的身份验证和授权会被人利用,以获取对敏感信息和操作的未授权访问。

缺陷

可能通过 Web 服务导致未授权访问的缺陷包括:

未使用身份验证

在 SOAP 头中以明文传递密码

在未加密的通信信道上使用基本身份验证

对策

可以使用以下对策防止未授权的访问:

在 SOAP 头中使用密码摘要进行身份验证。

在 SOAP 头中使用 Kerberos 票证进行身份验证。

在 SOAP 头中使用 X.509 证书进行身份验证。

使用 Windows 身份验证。

使用基于角色的授权来限制对 Web 服务的访问。这可以通过使用 URL 授权控制对 Web 服务文件 (.asmx) 的访问,或者通过在 Web 方法级使用主体–权限要求来实现。

参数操作

所谓参数操作是指对 Web 服务使用者和 Web 服务之间发送的数据进行未授权的修改。例如,可能在通过一个中间节点向目的地传输途中,攻击者可截获一个 Web 服务消息,然后在消息发送到预期终结点之前将其修改。

缺陷

导致参数操作可能发生的缺陷包括:

消息没有进行数字签名以提供防篡改功能

消息没有进行加密以提供私密性和防篡改

对策

可以使用以下对策防止参数操作:

对消息进行数字签名。数字签名可用于在接收端验证消息是否没有在传递途中被篡改。

加密消息负载以提供私密性和防篡改。

网络侦听

通过网络侦听,攻击者能够在 Web 服务消息跨网络传输时查看这些消息。例如,攻击者可以使用网络监视软件获取 SOAP 消息中包含的敏感数据。可能包括敏感的应用程序级数据或者凭据信息。

缺陷

导致网络侦听可能成功实施的缺陷包括:

在 SOAP 头中以明文传递凭据

未使用消息级加密

未使用传输级加密

对策

可以使用以下对策在敏感 SOAP 消息跨网络传输时进行保护:

使用传输级加密(如 SSL 或者 IPSec)。只有在您可控制两端终结点时这种对策才适用。

加密消息负载以提供私密性。这种方法在消息在去最终目的地的途中需要通过一个中间节点的场景中适用。

配置数据的泄漏

Web 服务泄漏配置数据有两种主要方式。第一种是,Web 服务可以支持 Web 服务描述语言 (WSDL) 的动态生成或者可支持在 Web 服务器上的可下载文件中提供 WSDL 信息。取决于您所处的场景,这可能是您并不希望发生的。

WSDL 用于说明一个 Web 服务的特性,例如,它的方法签名和所支持的协议。

第二种是,由于不适当的异常处理,Web 服务可能泄漏对攻击者有用的敏感的内部实现细节。

缺陷

可能导致配置数据泄漏的缺陷包括:

可从 Web 服务器下载无限制的 WSDL 文件

存在受限的 Web 服务支持 WSDL 的动态生成,而且允许未授权的使用者获取 Web 服务特性

脆弱的异常处理

对策

可以使用以下对策防止有害的配置数据泄漏:

使用 NTFS 权限对 WSDL 文件的访问进行授权。

删除 Web 服务器上的 WSDL 文件。

禁用文档协议以防止 WSDL 的动态生成。

捕获异常并向客户端引发一个 SoapException 异常或者 SoapHeaderException 异常(这两个异常将只返回最少和无害的信息)。

消息重放

Web 服务消息可能通过多个中间服务器传递。通过消息重放攻击,攻击者可捕获和复制一个消息,并将其重放给模拟客户端的 Web 服务。消息可能会被修改,也可能不会。

缺陷

导致消息重放可能发生的缺陷包括:

消息未加密

消息未进行数字签名以防止篡改

没有检测到重复消息,因为未使用唯一消息 ID

攻击

最常见的消息重放攻击类型包括:

基本重放攻击。攻击者捕获并复制一个消息,然后重放同一消息,并模拟客户端。这种重放攻击不需要恶意用户知道消息的内容。

中间人攻击。攻击者捕获消息然后修改部分内容,例如,发货地址,然后将其重放给 Web 服务。

对策

可以使用以下对策应对消息重放威胁:

使用加密的通信信道,例如 SSL。

加密消息负载以提供消息的私密性和防篡改。虽然这无法防止基本重放攻击,但是的确可以防止中间人攻击(消息的内容在重放之前进行修改)。

每个请求使用唯一的消息 ID 或者 nonce 值以检测重复,并对消息进行数字签名以提供防篡改功能。

nonce 值是用于请求的一种唯一加密值。

当服务器响应客户端时,它发送一个唯一 ID 并对消息(包括 ID)进行数字签名。当客户端发出另一个请求时,客户端将在消息中包括此 ID。服务器需要确保前一个消息中发送给客户端的 ID 也包含在客户端新的请求中。如果 ID 不同,服务器将拒绝此请求并认为它遭受了重放攻击。

攻击者无法盗用消息 ID,因为消息进行了数字签名。请注意这只能保护服务器不受从客户端使用消息请求发起的重放攻击,对于客户端并没有提供任何重放响应的保护。

返回页首

设计注意事项

在开始开发 Web 服务之前,有一些问题需要在设计时考虑。重要的安全注意事项有:

身份验证要求

私密性和完整性要求

资源访问标识

代码访问安全

身份验证要求

如果您的 Web 服务提供敏感的或者限制性的信息,它需要对调用方进行身份验证以支持授权。在 Windows 环境中,可以使用 Windows 身份验证。但是,当您不能控制两端的终结点的时候,可以使用 WSE 提供身份验证解决方案,这种解决方案遵守新出现的 WS-Security 标准。WSE 为使用 SOAP 头传递身份验证详细信息(形式为用户名和密码、Kerberos 票证、X.509 证书或者自定义令牌)提供了一个标准框架。有关更多信息,请参阅本单元后面的“身份验证”部分。

私密性和完整性要求

如果要在 Web 服务请求或者响应消息中传递敏感的应用程序数据,应该考虑如何才能保证它们在传输途中保持私密性、防止被修改。WSE 通过数字签名提供了完整性检查,它还支持 XML 加密以加密整个消息负载中的敏感元素。这种方法的优点在于,它是以新出现的 WS-Security 标准为基础的,它为需要通过多个中间节点传递的消息提供了一种解决方案。

另一种替代方案是通过 SSL 或者 IPSec 信道使用传输级加密。这些解决方案只适用于可控制两端的终结点的场合。

资源访问标识

默认时,ASP.NET Web 服务并不模拟,而且要使用最低特权的 ASPNET 进程帐户进行本地和远程资源访问。可以使用这个 ASPNET 进程帐户访问远程网络资源,如通过在数据库服务器上创建镜像的本地帐户访问要求进行 Windows 身份验证的 SQL Server。

在 Windows Server 2003 上,默认时使用网络服务帐户运行 Web 服务。

有关使用 ASP.NET 进程帐户进行远程数据库访问的更多信息,请参阅“保护 ASP.NET 应用程序的安全”单元中“数据访问”部分。

如果您使用模拟,适用于 Web 应用程序的问题和注意事项也适用于 Web 服务。有关更多信息,请参阅“构建安全的 ASP.NET Web 页和控件”单元和“保护 ASP.NET 应用程序的安全”单元中的“模拟”部分。

代码访问安全

考虑在目标部署环境中由安全策略定义的信任级别。Web 服务的信任级别是由其 <trust> 元素的配置定义的,它会影响 Web 服务可访问的资源的类型和它可执行的其他特权操作。

同样,如果您从一个 ASP.NET Web 应用程序调用 Web 服务,Web 应用程序的信任级别将决定它可调用的 Web 服务的范围。例如,一个配置为 Medium 信任的 Web 应用程序,默认时只能调用本地计算机上的 Web 服务。

有关从 Medium 和其他部分信任 Web 应用程序调用 Web 服务的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。

返回页首

输入验证

与任何接受输入数据的应用程序一样,Web 服务也必须验证传给它们的数据,从而实施业务规则并防止潜在的安全问题。用 WebMethod 属性标记的 Web 方法是 Web 服务的入口点。Web 方法可以接受强类型的输入参数或者类型选择较宽的参数,经常是以字符串数据的形式传入。这通常是由 Web 服务所设计面向的使用者的类型和范围所决定的。

强类型参数

如果您使用 .NET Framework 类型系统所说明的强类型参数,例如整数、双精度、日期或者其他自定义的对象类型如 Address 或者 Employee,自动生成的 XML 架构定义 (XSD) 架构将包含数据的类型说明。使用者可以使用这种类型化说明构造发送给 Web 方法的 SOAP 请求内适当格式化的 XML。ASP.NET 然后使用 System.Xml.Serialization.XmlSerializer 类将传入的 SOAP 消息反序列化为公共语言运行库 (CLR) 对象。以下示例显示了一个 Web 方法,它接受由内置数据类型组成的强类型输入。

[WebMethod]public void CreateEmployee(string name, int age, decimal salary) {...}

在前面的例子中,.NET Framework 类型系统将自动执行类型检查。为了验证通过 name 字段提供的字符范围,可以使用一个正则表达式。例如,以下代码说明了如何使用 System.Text.RegularExpressions.Regex 类约束输入字符的可能范围,并且验证参数长度。

if (!Regex.IsMatch(name, @"^[a-zA-Z‘.`-´\s]{1,40}$")){// Invalid name}

有关正则表达式的更多信息,请参阅“构建安全的 ASP.NET Web 页和控件”单元中的“输入验证”部分。以下示例显示了一个接受自定义 Employee 数据类型的 Web 方法。

using Employees;  // Custom namespace[WebMethod]public void CreateEmployee(Employee emp) { ... }

使用者需要了解 XSD 架构,才能调用您的 Web 服务。如果使用者是一个 .NET Framework 客户端应用程序,则它可以直接传入一个 Employee 对象,如下所示:

using Employees;Employee emp = new Employee();// Populate Employee fields// Send Employee to the Web servicewsProxy.CreateEmployee(emp);

而不是基于 .NET Framework 的使用者应用程序则必须根据 Web 服务的负责单位所提供的架构定义,人工构造 XML 输入。

这种强类型方法的优点在于,.NET Framework 可以根据类型定义为您分析输入数据并对其进行验证。但是,在 Web 方法内部,可能还是需要对输入数据进行约束。例如,虽然类型系统确认了 Employee 对象是有效的,您可能还是需要对 Employee 字段执行进一步验证。可能需要验证雇员的出生日期是否早于 18 年前。可能需要使用正则表达式对可用于姓名字段的字符范围进行约束,等等。

有关约束输入的更多信息,请参阅“构建安全的 ASP.NET Web 页和控件”单元中的“输入验证”部分。

类型选择较宽的参数

如果您使用字符串参数或者字节数组传递任意数据,就丧失了 .NET Framework 类型系统的许多好处。您必须人工分析输入数据以对其进行验证,因为自动生成的 WSDL 只是将参数描述为 xsd:string 类型的字符串输入。需要如下例所示通过程序对类型、长度、格式和范围进行检查。

[WebMethod]public void SomeEmployeeFunction(string dateofBirth, string SSN){. . .// EXAMPLE 1: Type check the datetry{DateTime dt = DateTime.Parse(dateofBirth).Date;}// If the type conversion fails, a FormatException is throwncatch( FormatException ex ){// Invalid date}// EXAMPLE 2: Check social security number for length, format, and rangeif( !Regex.IsMatch(empSSN,@"^\d{3}-\d{2}-\d{4}$",RegexOptions.None)){// Invalid social security number}}

XML 数据

在典型的企业对企业场合中,使用者经常需要传递表示业务文档如采购定单或者销售发票的 XML 数据。在输入数据得到处理或者传给下游组件之前,它的有效性必须由 Web 方法通过程序进行验证。

客户端和服务器必须建立一个描述 XML 的架构,并对其达成一致。以下代码片段说明了一个 Web 方法如何使用 System.Xml.XmlValidatingReader 类验证输入数据,在此例中,输入数据描述了一个简单的定单。请注意 XML 数据是通过一个简单的字符串参数传递的。

using System.Xml;using System.Xml.Schema;[WebMethod]public void OrderBooks(string xmlBookData){try{// Create and load a validating readerXmlValidatingReader reader = new XmlValidatingReader(xmlBookData,XmlNodeType.Element,null);// Attach the XSD schema to the readerreader.Schemas.Add("urn:bookstore-schema",@"http://localhost/WSBooks/bookschema.xsd");// Set the validation type for XSD schema.// XDR schemas and DTDs are also supportedreader.ValidationType = ValidationType.Schema;// Create and register an event handler to handle validation errorsreader.ValidationEventHandler += new ValidationEventHandler(ValidationErrors );// Process the input datawhile (reader.Read()){. . .}// Validation completed successfully}catch{. . .}}// Validation error event handlerprivate static void ValidationErrors(object sender, ValidationEventArgs args){// Error details available from args.Message. . .}

以下片段说明了使用者如何调用前面的 Web 方法:

string xmlBookData = "" +"Building Secure ASP.NET Applications" +"0735618909" +"1" +"";BookStore.BookService bookService = new BookStore.BookService();bookService.OrderBooks(xmlBookData));

前面的例子使用以下的简单 XSD 架构验证输入数据。

下表显示了 XSD 架构中可以使用的其他复杂的元素定义,可以进一步约束单独的 XML 元素。

表 1 XSD 架构元素示例 说明 示例

使用正则表达式约束 XML 元素

                                                                        

将十进制值约束为小数点之后有两位数字

                                                                        

约束输入字符串的长度

                                                                                     

将输入约束为一个枚举类型定义的值

                                                                                    

有关更多信息,请参阅 Microsoft 知识库文章:

307379,“How To:Validate an XML Document by Using DTD, XDR, or XSD in Visual C# .NET”。

318504,“How To:Validate XML Fragments Against an XML Schema in Visual C#.NET”。

SQL 注入式攻击

SQL 注入使攻击者可使用 Web 服务的数据库登录执行数据库中的任意命令。SQL 注入对于使用输入数据构造 SQL 查询的 Web 服务而言,是一个潜在的问题。如果您的 Web 方法需要访问数据库,它们应该使用 SQL 参数,理想情况下是使用参数化的存储过程进行访问。SQL 参数可验证输入的类型和长度,确保输入被当作文本而不是可执行代码进行处理。有关这种和其他 SQL 注入对策的更多信息,请参阅“构建安全的数据访问”单元中的“输入验证”部分。

跨站点脚本攻击

通过跨站点脚本攻击 (XSS),攻击者可利用您的应用程序在客户端执行恶意脚本。如果您从一个 Web 应用程序中调用 Web 服务,并从 Web 服务以 HTML 数据流的形式将输出发送回客户端,XSS 将成为一个潜在的问题。在这种情况下,您应该对从 Web 应用程序中 Web 服务接收的输出进行编码,然后再将其返回给客户端。这在您并不拥有 Web 服务而它又在 Web 应用程序的信任边界之外时,尤其重要。有关 XSS 对策的更多信息,请参阅“构建安全的 ASP.NET Web 页和控件”单元中的“输入验证”部分。

返回页首

身份验证

如果 Web 服务需要输出敏感的、受限的数据,或者如果需要提供受限的服务,则它需要对调用方进行身份验证。身份验证方案有很多,大致可以分为三类:

平台级身份验证

消息级身份验证

应用程序级身份验证

平台级身份验证

如果您可控制两端的终结点,而且两端的终结点都在同样的或者可信任的域中,那么可以使用 Windows 身份验证对调用方进行身份验证。

基本身份验证

可以使用 IIS 为基本身份验证配置 Web 服务的虚拟目录。通过这种方式,使用者必须配置代理,并提供用户名和密码形式的凭据。然后在每次 Web 服务通过代理请求的时候由代理传递它们。凭据是以明文形式传递的,所以应该只在 SSL 中使用基本身份验证。

以下代码片段说明了 Web 应用程序如何提取最终用户所提供的基本身份验证凭据,然后使用它们调用在 IIS 中配置为基本身份验证的一个下游 Web 服务。

// Retrieve client‘s credentials (available with Basic authentication)string pwd = Request.ServerVariables["AUTH_PASSWORD"];string uid = Request.ServerVariables["AUTH_USER"];// Set the credentialsCredentialCache cache = new CredentialCache();cache.Add( new Uri(proxy.Url), // Web 服务 URL"Basic",new NetworkCredential(uid, pwd, domain) );proxy.Credentials = cache;

集成 Windows 身份验证

可以使用 IIS 将 Web 服务的虚拟目录配置为使用集成 Windows 身份验证,这样将根据客户端和服务器的环境选择 Kerberos 或者 NTLM 身份验证。与基本身份验证相比,这种方式的优点在于,凭据不用跨网络发送,从而消除了网络侦听威胁。

为了调用配置为集成 Windows 身份验证的 Web 服务,使用者必须显式地配置代理的 Credentials 属性。

为了将客户端的 Windows 安全上下文(可能来自模拟线程标记或者进程标记)传递给 Web 服务,可以将 Web 服务代理的 Credentials 属性设置为 CredentialCache.DefaultCredentials,如下所示。

proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

您还可以使用一个显式的凭据集,如下所示:

CredentialCache cache = new CredentialCache();cache.Add( new Uri(proxy.Url), // Web 服务 URL"Negotiate",         // Kerberos or NTLMnew NetworkCredential(userName, password, domain));proxy.Credentials = cache;

如果您需要指定显式的凭据,不用将它们硬编码或者以明文存储。使用 DPAPI 加密帐户凭据并将加密数据存储在 Web.config 中的 <appSettings> 元素中,或者一个受限的注册表项下。

有关平台级身份验证的更多信息,请参阅“Microsoft patterns & practices 第 I 卷,构建安全的 ASP.NET Web 应用程序:身份验证、授权和安全通讯”中的“Web 服务安全”部分,网址:http://msdn.microsoft.com/library/en-us/dnnetsec/html/secnetlpMSDN.asp?frame=true。

消息级身份验证

可以使用 WSE 实现一种消息级身份验证解决方案,它符合新出现的 WS-Security 标准。这种方法使您可通过使用 SOAP 头以标准的方式传递身份验证令牌。

当双方同意使用 WS-Security 时,还必须就身份验证令牌的精确格式取得一致。

WSE 可使用和支持以下类型的身份验证令牌:

用户名和密码

Kerberos 票证

X.509 证书

用户名和密码

您可以在 SOAP 头中发送用户名和密码凭据。但是,因为这些凭据是通过明文发送的,为了防止网络侦听威胁,这种方法只应与 SSL 结合使用。凭据是作为 SOAP 头中 <Security> 元素的一部分发送的,如下所示。

BobYourStr0ngPassWord

用户名和密码摘要

可以发送密码摘要来代替发送明文的密码。摘要是一种 UTF8 编码密码的 Base64 编码 SHA1 散列值。但是,除非这种方法是在安全信道使用,数据仍然可被拥有网络监视软件的攻击者所截获,并再次用来获取对 Web 服务的已经过身份验证的访问权限。为了帮助应对这种重放攻击威胁,可以将摘要与 nonce 值和创建时间戳结合使用。

带有 nonce 值和时间戳的用户名和密码摘要

这种方法中,摘要是 nonce 值、创建时间戳和密码的 SHA1 散列值,如下所示。

digest = SHA1(nonce + creation timestamp + password)

这种方法中,Web 服务必须维护一个 nonce 值表,并拒绝任何包含着重复 nonce 值的消息。虽然这种方法有助于保护密码,并为防止重放攻击提供基础,但是在计算到期时间上受使用者和提供者之间的时钟同步问题影响很大,而且它无法防止攻击者捕获消息、修改 nonce 值然后将消息重放到 Web 服务。为了解决这种威胁,消息必须进行数字签名。使用 WSE,您可以使用自定义令牌或者 X.509 证书对消息进行数字签名。这样可根据公钥和私钥对提供防篡改和身份验证。

Kerberos 票证

您可以发送包含 Kerberos 票证的安全令牌,如下所示。

U87GGH91TT ...

X.509 证书

您还可以通过将 X.509 证书作为身份验证令牌发送提供身份验证。

Hg6GHjis1 ...

有关以上方法的更多信息,请参阅 WSE 中附带的示例。

应用程序级身份验证

您可以通过在应用程序中使用自定义 SOAP 头设计和构建自己的自定义身份验证。在此之前,需要查看平台和 WSE 提供的功能,以确定是否可以使用任何功能。如果您必须使用自定义身份验证机制,而且需要使用加密技术,那么应该使用 System.Security.Cryptography 命名空间公开的标准加密算法。

返回页首

授权

在身份验证之后,您可以根据调用方的身份或者角色成员资格,限制调用方只拥有 Web 服务所公开功能的一个子集。您可以对服务的终结点(在 .asmx 文件级)、单独的 Web 方法或者 Web 方法中特定功能的访问进行限制。

Web 服务终结点的授权

如果 Web 服务配置为集成 Windows 身份验证,可以在您的 Web 服务 (.asmx) 文件上根据原始调用方的安全上下文配置 NTFS 权限以控制访问。这种授权是通过 ASP.NET FileAuthorizationModule 执行的,无需模拟。

无论身份验证类型如何,都可以使用 ASP.NET UrlAuthorizationModule 控制对 Web 服务 (.asmx) 文件的访问。通过在 Machine.config 或者 Web.config 中的 <authorization> 元素中添加 <allow> 和 <deny> 元素可以进行这种配置。

有关两种形式的授权的更多信息,请参阅“保护 ASP.NET 应用程序的安全”单元中的“授权”部分。

Web 方法授权

可以使用声明性的主体权限要求,根据调用方的身份或者角色成员资格控制对单独 Web 方法的访问。 调用方的身份和角色成员资格是由与当前 Web 请求相关的主体对象(通过 HttpContext.User 访问)维护的。

 [PrincipalPermission(SecurityAction.Demand, Role=@"Manager")][WebMethod]public string QueryEmployeeDetails(string empID){}

有关主体权限要求的更多信息,请参阅“构建安全的 ASP.NET Web 页和控件”单元中的“授权”部分。

编程授权

可以通过调用 Web 方法中的 IPrincipal.IsInRole,使用命令性权限检查或者显式的角色检查实现细致的授权逻辑,如下所示。

// This assumes non-Windows authentication. With Windows authentication// cast the User object to a WindowsPrincipal and use Windows groups as// role namesGenericPrincipal user = User as GenericPrincipal;if (null != user){if ( user.IsInRole(@"Manager") ){// User is authorized to perform manager functionality}}
返回页首

敏感数据

如果 Web 服务请求或者响应消息需要传递敏感应用程序数据(例如,信用卡号码、雇员详细情况等等)的话,就必须解决在中间应用程序节点受到的网络侦听或者信息泄漏的威胁。

在一个封闭环境中,您可控制两端的终结点,因此可以使用 SSL 或者 IPSec 提供传输层加密。在其他环境中并且消息是通过中间应用程序节点路由的,因此需要消息级解决方案。WS-Security 标准以 WWW 联合会 (W3C) XML 加密标准为基础定义了一个机密服务,可以用来在传输 SOAP 消息之前加密其部分或者全部 SOAP 消息。

XML 加密

您可以用三种不同的方式加密所有或者部分 SOAP 消息:

使用 X.509 证书的不对称加密

使用共享密钥的对称加密

使用自定义二进制令牌的对称加密

使用 X.509 证书的不对称加密

在此方法中,使用者使用 X.509 证书的公钥部分加密 SOAP 消息。该消息将只能被拥有对应私钥的服务解密。

Web 服务必须能够访问相关的私钥。默认时,WSE 会在本地机器存储区中搜索 X.509 证书。可以使用 Web.config 中的 <x509> 配置元素将存储位置设置为当前用户存储区,如下所示。

如果您使用用户存储区,则必须加载 Web 服务进程帐户的用户配置文件。如果您使用默认 ASPNET 最低特权本地帐户运行 Web 服务,.NET Framework 的 1.1 版需要加载此帐户的用户配置文件,从而使用户密钥存储区变为可访问状态。

对于使用 .NET Framework 1.0 版构建的 Web 服务,并不加载 ASPNET 用户配置文件。这种情况下,有两种选择。

使用自定义的最低特权帐户运行 Web 服务(前面已经用此帐户通过交互方式登录到 Web 服务器),创建了一个用户配置文件。

将密钥存储在本地机器存储区中,并授予访问 Web 服务进程帐户的权限。在 Windows 2000 上,默认时这是 ASPNET 帐户。在 Windows Server 2003 上,默认时这是网络服务帐户。

为了授予访问权限,使用 Windows 资源管理器在以下文件夹(这些文件夹将完全控制权限授予 Web 服务进程帐户)配置 ACL。

\Documents and Settings\All Users\Application Data            Microsoft\Crypto\RSA\MachineKeys            

有关更多信息,请参阅 WSE 文档中的“Managing X.509 Certificates,”、“Encrypting a SOAP Message Using an X.509 Certificate,”和“Decrypting a SOAP Message Using an X.509 Certificate”部分。

使用共享密钥的对称加密

使用对称加密时,Web 服务及其使用者共享一个密钥,对 SOAP 消息进行加密和解密。这种加密比不对称加密要快,虽然使用者和服务的提供者必须使用某种带外机制共享密钥。

有关更多信息,请参阅 WSE 文档中的“Encrypting a SOAP Message Using a Shared Key”和“Decrypting a SOAP Message Using a Shared Key”部分。

使用自定义二进制令牌的对称加密

您还可以使用 WSE 定义一个自定义二进制令牌,封装用来加密和解密消息的自定义安全凭据。您的代码需要两个类。发送器类必须从 BinarySecurityToken 类派生,它用于封装自定义安全凭据和加密消息。接收类必须从 DecryptionkeyProvider 类中派生,它用于检索密钥和解密消息。

有关更多信息,请参阅 WSE 文档中的“Encrypting a SOAP Message Using a Custom Binary Security Token”和“Decrypting a SOAP Message Using a Custom Binary Security Token”部分。

加密部分消息

默认时,WSE 将加密整个 SOAP 体,并不加密 SOAP 头信息。但是,也可以使用 WSE 通过编程加密和解密消息的某些部分。

有关更多信息,请参阅 WSE 文档中的“Specifying the Parts of a SOAP Message that are Signed or Encrypted”部分。

返回页首

参数操作

与 Web 服务相关的参数操作,指的是这样的威胁:在消息请求或者响应在使用者和服务之间传输途中,攻击者能够以某种方式修改消息负载。

为了解决这种威胁,您可以对 SOAP 消息进行数字签名,以允许消息的接收者使用加密技术验证消息自数字签名之后是否没有被更改。有关更多信息,请参阅 WSE 文档中的“Digitally Signing a SOAP Message”部分。

返回页首

异常管理

返回给使用者的异常细节应该只包含最低级别的信息,不能暴露任何内部实现细节。例如,考虑如下的允许传播给使用者的系统异常。

System.Exception: User not in managers roleat EmployeeService.employee.GiveBonus(Int32 empID, Int32 percentage) in c:\inetpub\wwwroot\employeesystem\employee.asmx.cs:line 207

上面所示的异常细节将目录结构和其他细节暴露给服务的使用者。这一信息可能被恶意用户用来记录虚拟目录路径,从而帮助进行进一步的攻击。Web 服务可引发三种类型的异常:

SoapException 对象。

这些对象可以由 CLR 或者 Web 方法的实现代码生成。

SoapHeaderException 对象

这些对象在使用者发送 SOAP 请求而服务未能正确处理时自动生成。

Exception 对象

Web 服务可引发自定义的从 System.Exception 派生的异常类型。准确的异常类型将因错误情况的不同而异。例如,可能是标准 .NET Framework 异常类型之一,如 DivideByZeroException 或者 ArgumentOutOfRangeException 等等。

无论异常类型如何,异常细节都会使用标准 SOAP 的 <Fault> 元素传播到客户端。用 ASP.NET 构建的客户端和 Web 服务不会直接分析 <Fault>元素,而是应该统一处理 SoapException 对象。这样客户端可以设置可捕获 SoapException 对象的 try 块。

如果从一个自定义的 HTTP 模块引发 SoapException 异常,它不会自动地序列化为 SOAP<Fault> 元素。这种情况下,必须人工创建 SOAP<Fault>。

使用 SoapException

以下代码显示了一个简单的 Web 方法,其中应用程序逻辑的验证失败了,因此生成了一个异常。发送给客户端的错误信息非常少。在本例中,为客户端提供了可用于调用支持的帮助桌面引用。在 Web 服务器上,将帮助桌面引用的详细错误说明记录起来,以帮助进行问题的诊断。

using System.Xml;using System.Security.Principal;[WebMethod]public void GiveBonus(int empID, int percentage){// Only managers can give bonuses// This example uses Windows authenticationWindowsPrincipal wp = (HttpContext.Current.User as WindowsPrincipal);if( wp.IsInRole(@"Domain\Managers")){// User is authorized to give bonus. . .}else{// Log error details on the server. For example://    "DOMAIN\Bob tried to give bonus to Employee Id 345667;//     Access denied because DOMAIN\Bob is not a manager."// Note: User name is available from wp.Identity.Name// Return minimal error information to client using a SoapExceptionXmlDocument doc = new XmlDocument();XmlNode detail = doc.CreateNode(XmlNodeType.Element,SoapException.DetailElementName.Name,SoapException.DetailElementName.Namespace);// This is the detail part of the exceptiondetail.InnerText = "User not authorized to perform requested operation";throw new SoapException("Message string from your Web 服务",SoapException.ServerFaultCode,Context.Request.Url.AbsoluteUri, detail, null );}}

处理可能出现的 SoapException 的使用方代码如下所示:

try{EmployeeService service = new EmployeeService();Service.GiveBonus(empID,percentage);}catch (System.Web.Services.Protocols.SoapException se){// Extract custom message from se.Detail.InnerTextConsole.WriteLine("Server threw a soap exception" + se.Detail.InnerText );}

Global.asax 中的应用程序级错误处理

ASP.NET Web 应用程序一般处理允许传播超出 Global.asax. 中的 Application_Error 事件处理程序中方法边界的应用程序级异常。这种功能在 Web 服务中是没有的,因为 Web 服务的 HttpHandler 会在异常到达其他处理程序之前捕获它。

如果需要应用程序级异常处理,请创建自定义 SOAP 扩展对其进行处理。有关更多信息,请参阅 MSDN 文章“Altering the SOAP Message using SOAP Extensions”,位于 .NET Framework SDK 的“Building Applications”部分中,网址是:http://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&DisplayLang=en。

返回页首

审核和日志记录

通过 Web 服务,可以使用平台级功能或者在 Web 方法实现中使用自定义代码,以审核和记录活动细节以及事务。

可以开发使用 System.Diagnostics.EventLog 类将操作记录到 Windows 事件日志的代码。从 Web 服务使用这个类的权限要求和技术与 Web 应用程序相同。有关更多信息,请参阅“构建安全的 ASP.NET 页和控件”单元中的“审核和日志记录”部分。

返回页首

代理注意事项

如果使用 WSDL 自动生成一个代理类与 Web 服务通信,应该验证所生成的代码和服务终结点,确保您是在与希望的 Web 服务而非被欺骗的服务通信。如果远程服务器上的 WSDL 文件未被保护,恶意用户就有可能篡改文件,改变终结点地址,从而可能影响您生成的代理代码。

具体而言,查看 .wsdl 文件中的 <soap:address> 元素,验证它是否指向期望的位置。如果通过 Add Web Reference 对话框使用 Visual Studio .NET 添加 Web 引用,向下滚动,查看服务终结点。

最后,无论是使用 Visual Studio.NET 添加 Web 引用还是使用 Wsdl.exe 手工生成代理代码,都要仔细检查代理代码,寻找任何可疑的代码。

可以将 Web 服务代理的 URL Behavior 属性设置为Dynamic,这样就可在 Web.config 中指定终结点地址了。

返回页首

代码访问安全注意事项

代码访问安全可限制 Web 服务代码可访问的资源和可执行的操作。ASP.NET Web 服务要受 ASP.NET 代码访问安全策略的约束,该策略是通过 Web 服务的 <trust> 元素进行配置的。

调用 Web 服务的 .NET Framework 使用方代码必须由代码访问安全策略授予 WebPermission 权限。WebPermission 的准确状态决定了可调用 Web 服务的范围。例如,可以约束代码使其只能调用本地 Web 服务或者指定服务器上的服务。

如果使用方代码有完全信任,它被授予无限的 WebPermission 权限,允许您调用任何 Web 服务。部分信任的使用方代码有以下限制:

如果从 Medium 信任的 Web 应用程序调用一个 Web 服务,默认时只能访问本地 Web 服务。

使用 WSE 类的使用方代码必须被授予完全信任。例如,如果您的 Web 服务代理类从 Microsoft.Web.Services.WebServicesClientProtocol(由 WSE 提供)派生,则完全信任是必需的。为了从部分信任 Web 应用程序使用 WSE,必须用沙箱保护对 Web 服务的调用。

有关从部分信任 Web 应用程序调用 Web 服务的更多信息,请参阅“在 ASP.NET 中使用代码访问安全”单元。有关 WebPermission 的更多信息,请参阅“代码访问安全实践”单元中的“Web 服务”部分。

返回页首

部署注意事项

您可选择的安全措施范围有多大,很大程度上取决于您的 Web 服务要覆盖的特定部署场景。如果构建的应用程序是在 intranet 中使用 Web 服务,则您可随意选择的安全措施和技术的范围是最大的。但是,如果您的 Web 服务是可以跨 Internet 公开访问的,您的选择范围就大受限制。本部分将叙述不同的部署情况对本单元中前面讨论的 Web 服务保护方法适用性的影响。

Intranet 部署

因为您可控制使用者应用程序、服务和平台,Intranet 通常能提供最大范围的保护 Web 服务安全的选择。

在 Intranet 场合中,您通常可从全部的身份验证和安全通信选项中进行选择。例如,如果使用者和服务在同样的域或者信任域中,可以决定使用 Windows 身份验证。您可以指定客户端应用程序的开发人员设置客户端代理的凭据属性,将用户的 Windows 凭据传递给 Web 服务。

Intranet 通信经常是通过专用网络传递,有一定的安全性。如果这种安全性不够,可以决定通过使用 SSL 加密通信。您还可以使用消息级安全,并在客户端和服务器上都安装 WSE,以处理两端的安全,而这对于应用程序而言是透明的。WSE 支持身份验证、数字签名和加密。

Extranet 部署

在 Extranet 情况下,可能需要跨 Internet 对数目有限的一些合作伙伴公开 Web 服务。用户群体依然是已知的、可预测的,还可能使用托管客户端应用程序,虽然它们来自不同的独立的环境。在这种情况下,需要一种适合双方而且不依赖于信任域的身份验证机制。

如果双方都可获得帐户信息,可以使用基本身份验证。如果您使用基本身份验证,要确保通过使用 SSL 保护好凭据。

SSL 只保护跨网络传输的凭据。如果恶意用户成功地在客户端机器本地安装了代理工具(如 sslproxy),并在通过 SSL 将调用转发给 Web 服务之前进行截获,则 SSL 是无法进行保护的。

在 Extranet 中可以采取的另一种选择,是使用 IIS 客户端证书身份验证代替传递显式的凭据。在这种情况下,调用方应用程序必须在调用时提供有效证书。Web 服务使用证书对调用方进行身份验证和对操作进行授权。有关更多信息,请参阅 MSDN 文章“构建安全的 ASP.NET 应用程序”(网址是 http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetch06.asp)中的“Extranet 安全”部分。

Internet 部署

如果您要对大量 Internet 使用者公开 Web 服务,而且需要进行身份验证,可以考虑的选择是充分进行约束。任何形式的平台级身份验证都不可能适合,因为使用者无法具有正确的域帐户以对应其凭据。当大量的客户端证书对目标 IIS Web 服务器(或者在它之前的 ISA Server)而言必须已知时,使用 IIS 客户端证书身份验证和传输层加密 (SSL) 也存在问题。这样,只剩下消息级和应用程序级身份验证和授权是最可能的选择了。服务的使用者所传递的凭据(以用户名、密码、证书、Kerberos 票证或者自定义令牌的形式)可以被 Web 服务基础结构 (WSE) 透明地进行验证,或者在目标服务中通过程序进行验证。很难控制客户端证书的规模。密钥管理(颁发和撤消)就成问题了。而且,基于证书的身份验证是资源密集型的,因此在有大量客户端时它会受可伸缩性问题的困扰。

SSL 通常可提供网络流量的加密(仅限于服务器端证书),但是也可以用消息级加密进行补充。

使用客户端证书,虽然从安全角度来看有其优点,但是经常会在用户数目很大时遇到问题。您必须仔细地管理证书,并且考虑应该如何将证书传递到客户端,还有更新、撤消等等事情。由于存在处理开销或者大规模大工作量的 Web 服务的加密/解密和证书验证,Internet 场景中的另一个潜在问题是解决方案的总可伸缩性。

返回页首

小结

WS-Security 是 Web 服务安全方面新出现的标准。该标准定义了通过使用 SOAP 头以标准方式传递安全令牌进行身份验证的各种选项。令牌可包括用户名、密码凭据、Kerberos 票证、X.509 证书或者自定义令牌。WS-Security 还解决了消息私密性和完整性问题。可以加密整个或者部分消息以提供私密性,对其进行数字签名以提供完整性。

在 Intranet 场景中,您控制着两端的终结点,可以使用平台级(如 Windows 身份验证)的安全选项。在更复杂的场景中,您无法控制两端的终结点,消息的路由通过中间应用程序节点,就需要消息级解决方案了。下面的部分“其他资源”列出了可用来跟踪新出现的 WS-Security 标准和相关 WSE 工具集的 Web 站点,这样您可构建符合此标准和其他新出现的 Web 服务标准的解决方案。

返回页首

其他资源

有关更多信息,参阅下列资源:

有关核对表的打印稿,请参阅“核对表:保护 Web 服务的安全。”

您可以从 Microsoft Web 服务开发人员中心主页(网址是 http://msdn.microsoft.com/webservices)下载 WSE。

有关 Web 服务身份验证、授权和安全通信的信息,请参阅“Microsoft patterns & practices 第 I 卷:构建安全的 ASP.NET Web 应用程序:身份验证、授权和安全通讯”的“Web 服务安全”部分,网址是:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch10.asp。

有关专门讲述 Web 服务安全的文章,请参阅 MSDN 文章,网址是:http://msdn.microsoft.com/webservices/building/security/default.aspx。

有关专门讲述 Web 服务增强的文章,请参阅 MSDN 文章,网址是:http://msdn.microsoft.com/webservices/building/wse/default.aspx。

有关在 Web 服务中使用 SSL 的信息,请参阅“Microsoft patterns & practices 第 I 卷:构建安全的 ASP.NET Web 应用程序:身份验证、授权和安全通讯”的“如何……”部分中的“如何使用 SSL 调用 Web 服务”,网址是: http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT14.asp。

有关在 Web 服务中使用客户端证书的信息,请参阅 MSDN 文章“如何:从 ASP.NET 使用客户端证书调用 Web 服务”,在“Microsoft patterns & practices 第 I 卷:构建安全的 ASP.NET Web 应用程序:身份验证、授权和安全通讯”的“如何……”部分中,网址是: http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT13.asp。

有关 WS-Security 的信息,请参阅 MSDN 文章“WS-Security: New Technologies Help You Make Your Web Services More Secure”,网址是:http://msdn.microsoft.com/msdnmag/issues/03/04/WS-Security/default.aspx。

有关 XML 加密的信息,请参阅 W3C XML Encryption Working Group在http://www.w3.org/Encryption/2001/。

转到原英文页面