简介
有一个一直让 Web 服务开发人员感到头疼的课题,那就是:如何使 IIS 和 ASP.NET Web 服务协同工作以提供安全性。现在,我们通过 IIS 来处理安全问题,并通过 ASP.NET 进行调节。ASP.NET 可以接受 IIS 提供的身份标识信息并使用该信息来了解调用者是谁,或者利用代码访问安全性在 Web 服务上执行特定操作。对于许多人而言,最大的问题是如何使 .NET 应用程序利用内置的 IIS 安全保护功能。在不远的将来,WS-Security 将是您的更佳选择。在那一天到来之前,HTTP 级的安全保护将是我们许多人用来保证信息安全的方法。
当以安全的方式执行 Web 方法时,必须涉及以下各项:
保密使侦听对话的实体不能直接看到数据。
完整性向接收者提供对 SOAP 消息所作更改进行检测的能力。
身份验证回答“调用者是谁”的问题。
授权回答“调用者是否有权访问该 Web 方法”的问题。
认可证明所发生的操作,以防止客户端在事务处理中欺诈或否认。
这些安全保护功能常常是配合使用的。身份验证允许授权和认可的发生。SSL 提供的保密措施也包括完整性和身份验证机制。本文假设您已经比较熟悉如何配合使用 SSL 和 IIS。如果您不熟悉,请查看本文末尾的资源。同时,建议您查找安装了证书服务器的 Microsoft® Windows® 服务器,或者在可用的 Windows 服务器上安装证书服务器。这将对理解本文有关 SSL 的部分有所帮助。
使用 SSL 进行加密和签名
任何时候当您需要对基于 HTTP 的 SOAP 消息进行保密时,都应该通过 SSL 运行服务。它将对通过线路查看数据传输的实体隐藏 Web 服务中的数据。
为了使用本节中的数据,在您的 Web 服务器的根目录下必须安装有 X.509 证书。有关如何执行此操作的信息,请参阅 HOWTO: Configure SSL in a Windows 2000 IIS 5.0 Test Environment Using Certificate Server 2.0 (Q290625)(英文)。正确安装证书后,您便可以为虚拟目录或特定文件选择强制执行 SSL 身份验证。
打开 Internet Information Services 管理控制台的步骤
在“开始”菜单中单击“运行”。
在“打开”编辑框中,键入 inetmgr。
单击“确定”。
这样,IIS 管理控制台就打开了。
为虚拟目录或特定文件请求 SSL 就是在 IIS 中选择正确的选项。要选择“正确的选项”,请浏览到 IIS 管理控制台中的虚拟目录。如果您想为可以通过给定的虚拟目录进行访问的所有 Web 服务请求 SSL,请右键单击该虚拟目录,单击“属性”,然后单击“目录安全性”选项卡。
如果只保护某个特定的 Web 服务,请右键单击与该 Web 服务关联的 .asmx 文件,单击“属性”,然后单击“文件安全性”选项卡。不管执行哪个步骤,您都将看到一个与图 1 类似的对话框。请在“安全通信”下,单击“编辑”,将打开如图 2 所示的“安全通信”对话框。
图 1:IIS 管理控制台中的“安全性”选项卡
图 2:“安全通信”对话框
默认情况下“需要安全通道 (SSL)”复选框没有被选中,请选中该复选框以请求 SSL。SSL 支持 40 位和 128 位加密。加密使用的位数越多,破译和找出原始位就越困难。这就是为特定的 .asmx 文件或整个 Web 服务启用 SSL 所要做的全部工作。这样,只要 Web 服务器的证书不受威胁,所有 Web 服务客户端和 Web 服务本身都将是安全的。SSL 使用包含公钥的 X.509 证书,可能还包含一个私钥。如果私钥被外部用户知道,则使用公钥加密的通信就可能会被外部用户侦测到,从而变得不安全。
一旦您将资源设置为通信时需要 SSL,则发送者和接收者之间传送的信息就将被加密并签名。也就是说,外部用户将无法阅读消息的内容。如果外部用户改变了消息的字节数,消息接收者可以检测到更改。
身份验证
为了利用 IIS 给您提供的身份验证,您需要编辑与您的 Web 服务关联的 Web.config 文件。要使用户的身份在 HttpContext 中可用,您需要将 /configuration/system.web/authentication/@mode 属性设置为 Windows。当 IIS 使用以下身份验证方式之一时,必须设置模式属性:基本、简要、集成 Windows 身份验证 (NTLM/Kerberos) 或 X.509 证书。上述任何一种身份验证提供的用户凭据都必须映射回本地计算机或 Active Directory 中的用户。
IIS 和正确的 Web.config 设置结合使用将使 Web 服务能够发现调用者的身份标识。作为新增的优点,请求上下文将假设调用者的身份。如果要利用 Windows 身份验证,Web.config 文件应该如下所示:
<configuration
<system.web
<authentication mode="Windows" /
<!-- 其他元素将放在此处 --
</system.web
</configuration
为了处理身份验证、审核和认可,打开 Windows 身份验证是很关键的。这样做的目的是使您的 Web 方法以调用者的身份运行。所有记录、访问检查等都是根据用户的权限来执行的。
为了强制 IIS 提供调用者的身份标识,您需要告诉 IIS 关闭匿名访问。就是这么简单,真的。要执行此操作,请返回并打开 inetmgr(单击“开始”-“运行”,然后键入 inetmgr)。浏览到所需的虚拟目录。右键单击虚拟目录或 .asmx 文件(这取决于您需要对虚拟目录中的所有文件实施身份标识还是仅对一个 Web 服务实施身份标识),然后单击“属性”。单击“目录安全性”选项卡,如图 1 所示。在“匿名访问和验证控制”中,单击“编辑”。将打开如图 3 所示的“身份验证方法”对话框。
图 3:禁用匿名访问的“身份验证方法”对话框
“身份验证方法”对话框允许您配置用户访问虚拟目录或文件的方法。要通过 HTTP 信息头传递用户凭据,您可以使用基本或简要身份验证。基本和简要身份验证均不提供任何确保消息安全的机制。传递用户凭据的机制由 RFC 2617: HTTP Authentication: Basic and Digest Access Authentication(英文)定义。基本上,使用一个名为 Authorization 的 HTTP 信息头来传递用户名和密码。对于基本身份验证而言,用户名/密码组合是以明文的方式发送的。不过,也不全是这样。实际上,用户名和密码是使用简单明文形式的 base64 编码方法来发送的。如果您不熟悉 base64 编码,可以使用二进制数据并以文本形式提供这些数据。对数据进行编码时,不使用机密/密钥。如果选择使用基本身份验证,则只能接受通过 SSL 的凭据。这可以保护 Web 服务和调用者免受试图攻击通道以捕获有效凭据集的实体的威胁。
还可以使用简要身份验证。如果选择此选项,您必须了解,许多 SOAP 工具包都不支持简要身份验证。因而,可以使用 Web 服务的工具包数量将受到限制。如果想知道调用者的身份,而目标 SOAP 工具包支持简要身份验证并且 SOAP 消息的内容不是特别重要,则请使用简要身份验证。简要身份验证使用名为 nonce 的共享机密为调用者的凭据进行加密。
基本和简要身份验证都使用质询-响应机制。正因为如此,在 Web 方法调用发生之前,客户端和接收器之间将发送多次请求和响应。在基本身份验证中,质询和响应的速度都相当快。事实上,如果客户端知道需要基本身份验证,它会提早提供基本凭据。这种提速可以是需要验证服务器证书并建立会话密钥的、基于 SSL 的连接中的临界值。在简要身份验证中,在凭据被加密前,需要交换 nonce。同样,在 Web 服务代码被执行之前需要执行一些握手操作。
要针对 Web 服务强制启用这些项,只需要在“身份验证方法”对话框中选中相应的框即可。如果您确认只需要获取已经过身份验证的用户,请确保取消选中“匿名访问”复选框。完成这一步后,您便可以在服务器端进行以下操作:
搜索调用者。
使用代码访问安全性限制调用者可以调用的方法。
以下 Web 服务返回当前的调用者信息:
[WebMethod]
public string WhoAmI() {
return "正在作为用户运行: " +
Thread.CurrentPrincipal.Identity.Name;
}
我们将修改一个调用该 Web 服务的简单的控制台应用程序。开始时,客户端如下所示:
static void Main(string[] args) {
localhost.Sample svc = new localhost.Sample();
try {
Console.WriteLine( svc.WhoAmI() );
} catch ( Exception ex ) {
Console.WriteLine( ex.ToString() );
} finally {
svc.Dispose();
}
}
如果没有对 Web 服务/应用程序应用安全保护,Main 函数将打印以下信息:
图 4:无安全保护运行,因而也没有身份标识
如果您通过图 3 中的对话框关闭匿名访问,客户端将无法访问 Web 服务。相反,将显示以下错误消息:
System.Net.WebException: 请求失败,HTTP 状态 401: 访问被拒绝。
为什么会是这样呢?默认情况下,Web 服务代理不包含任何关于调用者或要传递的凭据的信息。因为不能验证自己的身份,调用 Web 方法的尝试失败,并且引发异常。如果您想为当前用户传递正确的凭据,最简单的方法是沿着当前用户的默认凭据