使用证书

对 Windows Communication Foundation (WCF) 安全进行编程时,通常使用 X.509 数字证书对客户端和服务器进行身份验证,以及对消息进行加密和数字签名。本主题将简要说明 X.509 数字证书的功能以及如何在 WCF 中使用它们,并提供一些主题的链接,这些主题对这些概念进行了深入说明,或揭示了如何使用 WCF 和证书来完成常见任务。

简言之,数字证书是公钥基础结构 **(PKI) 的一部分,而公钥基础结构是数字证书、证书颁发机构和其他注册机构的系统,它使用公钥加密对电子事务所涉及的每一方的有效性进行确认和身份验证。证书颁发机构颁发证书,每个证书都具有一组包含数据的字段,例如使用者(向其颁发证书的实体)、有效日期(证书的有效日期)、颁发机构(颁发证书的实体)和公钥。在 WCF 中,这些属性中的每一个都作为 Claim 进行处理,而每个声明又进一步分为两种类型:标识和权限。有关 X.509 证书的更多信息,请参见 X.509 公钥证书。有关 WCF 中的声明和授权的更多信息,请参见使用标识模型管理声明和授权。有关实现 PKI 的更多信息,请参见 Windows Server 2008 R2 - 证书服务

证书的主要功能是向其他各方验证证书所有者的身份。证书包含所有者的公钥,所有者保留着私钥。公钥可用来对发送给证书所有者的消息进行加密。只有所有者才能访问私钥,因此,只有所有者才能解密这些消息。

证书必须由证书颁发机构(通常是第三方证书颁发机构)颁发。在 Windows 域中,包括一个证书颁发机构,可以用来向域中的计算机颁发证书。

查看证书

若要使用证书,通常需要查看证书并检查其属性。使用 Microsoft 管理控制台 (MMC) 管理单元工具,很容易实现这一任务。有关更多信息,请参见 如何:使用 MMC 管理单元查看证书.

证书存储区

证书存放在存储区中。主要的存储区位置有两个,它们进一步分为子存储区。如果您是计算机的管理员,就可以使用 MMC 管理单元工具查看这两个主要存储区。非管理员只能查看当前用户存储区。

  • 本地计算机存储区。该存储区包含计算机进程(例如 ASP.NET)访问的证书。此位置用于存储向客户端验证服务器身份的证书。

  • 当前用户存储区。交互式应用程序通常将证书放在此位置,供计算机的当前用户使用。如果要创建客户端应用程序,通常会将向服务验证用户身份的证书放在此处。

这两个存储区进一步分为子存储区。使用 WCF 编程时,最重要的子存储区包括:

  • 受信任的根证书颁发机构。使用此存储区中的证书可以创建证书链,通过证书链,可以追溯到此存储区中的证书颁发机构证书。

    ms731899.Important(zh-cn,VS.100).gif 注意:
    本地计算机隐式信任放置在此存储区中的任何证书,即使证书不是来自受信任的第三方证书颁发机构,也是如此。因此,除非完全信任颁发机构并了解后果,否则不要将任何证书放入此存储区。

  • 个人。此存储区用于放置与计算机用户关联的证书。通常,此存储区用于存放受信任的根证书颁发机构存储区中的证书颁发机构证书之一所颁发的证书。此外,此处还可存放应用程序自行颁发并且信任的证书。

有关证书存储区的更多信息,请参见证书存储区

选择存储区

证书存储位置的选择,取决于服务或客户端运行的方式和时间。适用以下一般规则:

  • 如果 WCF 服务承载于某个 Windows 服务中,则使用**“本地计算机”**存储区。请注意,要将证书安装到本地计算机存储区,需要有管理员权限。

  • 如果服务或客户端是在某个用户帐户下运行的应用程序,则使用**“当前用户”**存储区。

访问存储区

与计算机上的文件夹一样,存储区也受访问控制列表 (ACL) 保护。在创建由 Internet 信息服务 (IIS) 承载的服务时,ASP.NET 进程运行在 ASP.NET 帐户下。该帐户必须有权访问包含服务所用证书的存储区。每个主要存储区都由一个默认访问列表保护,但这些列表是可以修改的。如果创建一个单独的角色访问存储区,则必须向该角色授予访问权限。若要了解如何使用 WinHttpCertConfig.exe 工具修改访问列表,请参见如何:创建开发期间使用的临时证书。有关在 IIS 中使用客户端证书的更多信息,请参见如何在 ASP.NET Web 应用程序中通过使用客户端证书进行身份验证来调用 Web 服务

链信任和证书颁发机构

证书是在某种层次结构中创建的,其中每个证书都链接到颁发该证书的 CA。该链接指向 CA 的证书。CA 的证书又链接到颁发原始 CA 证书的 CA。这一过程不断重复,直至到达根 CA 的证书。根 CA 的证书将以继承方式受到信任。

使用数字证书对实体进行身份验证时就依赖这一层次结构,它也称为信任链。在 MMC 管理单元中,双击任何证书,再单击**“证书路径”**选项卡,可以查看任何证书链。有关导入证书颁发机构的证书链的更多信息,请参见如何:指定用于验证签名的证书颁发机构证书链 (WCF)

ms731899.note(zh-cn,VS.100).gif注意:
通过将颁发机构的证书放入受信任的根颁发机构证书存储区中,可以向任何颁发机构指定受信任的根颁发机构。

禁用链信任

在创建新服务时,可能会使用不是由受信任的根证书颁发的证书,或者颁发证书本身可能不在受信任的根证书颁发机构存储区中。如果仅为了开发目的,可以暂时禁用检查证书信任链的机制。为此,需要将 CertificateValidationMode 属性设置为 PeerTrustPeerOrChainTrust。这两种模式都指定,证书可以是自行颁发的(对等信任),也可以是信任链的一部分。在下列所有类上,都可以设置此属性。

属性

X509ClientCertificateAuthentication

System.ServiceModel.Security.X509ClientCertificateAuthentication.CertificateValidationMode

X509PeerCertificateAuthentication

System.ServiceModel.Security.X509PeerCertificateAuthentication.CertificateValidationMode

X509ServiceCertificateAuthentication

System.ServiceModel.Security.X509ServiceCertificateAuthentication.CertificateValidationMode

IssuedTokenServiceCredential

System.ServiceModel.Security.IssuedTokenServiceCredential.CertificateValidationMode

此外,也可以通过配置设置此属性。下列元素用于指定验证模式:

自定义身份验证

使用 CertificateValidationMode 属性,还可以对证书的身份验证方式进行自定义。默认情况下,级别设置为 ChainTrust。若要使用 Custom 值,还必须将 CustomCertificateValidatorType 属性设置为程序集和用于验证证书的类型。若要创建自定义验证程序,必须从抽象 X509CertificateValidator 类继承。

在创建自定义身份验证器时,要重写的最重要方法是 Validate 方法。有关自定义身份验证的示例,请参见 X.509 证书验证程序示例。有关更多信息,请参见 自定义凭据和凭据验证.

使用 Makecert.exe 生成证书链

证书创建工具 (Makecert.exe) 可以创建 X.509 证书和私钥/公钥对。可以将私钥保存在磁盘上,然后用它来颁发和签名新证书,从而模拟链状证书的层次结构。此工具仅在开发服务时用作辅助手段,决不可以用来为实际部署创建证书。在开发 WCF 服务时,可使用 Makecert.exe 按照下列步骤生成信任链。

使用 Makecert.exe 生成信任链

  1. 使用 MakeCert.exe 工具创建一个临时根证书颁发机构(自签名)证书。将私钥保存到磁盘上。

  2. 使用此新证书颁发另一个包含公钥的证书。

  3. 将根颁发机构证书导入到受信任的根证书颁发机构存储区中。

  4. 有关分步说明,请参见如何:创建开发期间使用的临时证书

要使用哪个证书?

关于证书的常见问题是要使用哪个证书以及使用它的原因。答案取决于是对客户端编程还是对服务编程。下面的信息提供了一个一般准则,但未对这些问题提供详尽解答。

服务证书

服务证书的主要任务是向客户端验证服务器的身份。客户端对服务器进行身份验证时所进行的初始检查之一是将**“主题”字段的值与用来联系服务的统一资源标识符 (URI) 进行比较:二者的 DNS 必须匹配。例如,如果服务的 URI 为“https://www.contoso.com/endpoint/”,则“主题”**字段也必须包含值“www.contoso.com”。

请注意,该字段可以包含多个值,每个值都以一个起始值前缀来指示其值。最常见的起始值是以“CN”表示公用名,例如“CN = www.contoso.com”。**“主题”字段还可能为空白,这种情况下,“主题备用名称”字段可以包含“DNS 名称”**值。

另请注意,证书**“预期目的”**字段的值应包含一个适当的值,例如“服务器身份验证”或“客户端身份验证”。

客户端证书

客户端证书通常不是由第三方证书颁发机构颁发的。相反,在当前用户位置的个人存储区中,通常包含由根证书颁发机构存放在此的证书,其预期目的为“客户端身份验证”。如果需要相互身份验证,则客户端可以使用此类证书。

联机吊销和脱机吊销

证书有效性

每个证书仅在给定时间段内有效,称为“有效期”。有效期由 X.509 证书的“有效起始日期”“有效结束日期”**字段定义。在身份验证过程中,将对证书进行检查以确定证书是否仍在有效期内。

证书吊销列表

在有效期内,证书颁发机构随时可以吊销证书。吊销证书有多种原因,例如危及证书私钥的安全。

如果证书吊销,则从被吊销证书继承的任何链都将无效,在身份验证过程中也不受信任。为了查看哪些证书被吊销,每个颁发机构都发布一个加盖了时间戳和日期戳的“证书吊销列表”**(CRL)。可以使用联机吊销或脱机吊销来查看此列表,方法是将以下类的 RevocationModeDefaultRevocationMode 属性设置为 X509RevocationMode 枚举值之一:X509ClientCertificateAuthenticationX509PeerCertificateAuthenticationX509ServiceCertificateAuthenticationIssuedTokenServiceCredential 类。所有属性的默认值都是 Online

此外,还可以使用 <authentication> of <clientCertificate> ElementserviceBehaviors section<authentication> of <clientCertificate> Element(在 endpointBehaviors section 中)和 (在 中)的 revocationMode 属性在配置中设置该模式。

SetCertificate 方法

在 WCF 中,必须经常指定一个或一组证书,供服务或客户端用来对消息进行身份验证、加密或数字签名。使用表示 X.509 证书的各个类的 SetCertificate 方法,可以以编程方式实现这一操作。下面的类使用 SetCertificate 方法指定一个证书。

方法

PeerCredential

SetCertificate

X509CertificateInitiatorClientCredential

SetCertificate

X509CertificateRecipientServiceCredential

SetCertificate

X509CertificateInitiatorServiceCredential

SetCertificate

SetCertificate 方法通过指定一个存储区位置和存储区、一个指定证书字段的“查找”类型(x509FindType 参数)和一个要在字段中查找的值来实现其功能。例如,下面的代码创建一个 ServiceHost 实例,并使用 SetCertificate 方法设置用于向客户端验证服务身份的服务证书。

Dim baseAddress As New Uri("http://cohowinery.com/services")
Dim sh As New ServiceHost(GetType(CalculatorService), baseAddress)
sh.Credentials.ServiceCertificate.SetCertificate( _
StoreLocation.LocalMachine, StoreName.My, _
X509FindType.FindBySubjectName, "cohowinery.com")
Uri baseAddress = new Uri("http://cohowinery.com/services");
ServiceHost sh = new ServiceHost(typeof(CalculatorService), baseAddress );
sh.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine, StoreName.My,
X509FindType.FindBySubjectName, "cohowinery.com");

具有相同值的多个证书

一个存储区可以包含多个具有相同主题名称的证书。这意味着如果将 x509FindType 指定为 FindBySubjectNameFindBySubjectDistinguishedName,并且多个证书具有相同的值,则会引发异常,这是因为 无法区分****需要的是哪个证书。通过将 x509FindType 设置为 FindByThumbprint,可以缓解这一问题。指纹字段包含一个唯一值,可以用来查找存储区中的特定证书。但是,这种方法也有缺点,如果证书已吊销或续订,则 SetCertificate 方法会失败,因为指纹也消失了。或者,如果证书不再有效,则身份验证将失败。缓解这一问题的方法是将 x590FindType 参数设置为 FindByIssuerName 并指定颁发机构的名称。如果不需要特定颁发机构,也可以设置一个其他的 X509FindType 枚举值,例如 FindByTimeValid

配置中的证书

此外,通过配置也可以设置证书。如果要创建服务,则在 serviceBehaviors section中指定凭据(包括证书)。如果要对客户端编程,则在 endpointBehaviors section中指定证书。

将证书映射到用户帐户

IIS 和 Active Directory 的一个功能是将证书映射到 Windows 用户帐户。有关此功能的更多信息,请参见 Map certificates to user accounts(将证书映射到用户帐户)。

有关使用 Active Directory 映射的更多信息,请参见 Mapping Client Certificates with Directory Service Mapping(使用目录服务映射来映射客户端证书)。

如果启用了这一功能,则可以将 X509ClientCertificateAuthentication 类的 MapClientCertificateToWindowsAccount 属性设置为 true。在配置中,可以将 <authentication> 元素的 mapClientCertificateToWindowsAccount 属性设置为 true,如下面的代码所示。

<serviceBehaviors>
 <behavior name="MappingBehavior">
  <serviceCredentials>
   <clientCertificate>
    <authentication certificateValidationMode="None" mapClientCertificateToWindowsAccount="true" />
   </clientCertificate>
  </serviceCredentials>
 </behavior>
</serviceBehaviors>

将 X.509 证书映射到表示 Windows 用户帐户的令牌,这一过程视为权限提升,这是因为一旦执行了映射,就可使用 Windows 令牌获得对受保护资源的访问权限。因此,域策略要求 X.509 证书在映射之前符合其策略。“SChannel”**安全数据包强制执行此要求。

使用 .NET Framework 3.5 版 或更高版本时,WCF 可以确保证书在映射到 Windows 帐户之前符合域策略。

在 WCF 第一版中,执行映射无需考虑域策略。因此,如果启用了映射,而 X.509 证书不满足域策略,则在第一版下运行正常的早期应用程序,可能会失败。

另请参见

参考

System.ServiceModel.Channels
System.ServiceModel.Security
System.ServiceModel
X509FindType

其他资源

保护服务和客户端的安全