使用证书

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

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

证书的主要功能是向其他各方验证主题的身份。此外,证书还包含主题的公钥**,主题则保留私钥。任何人都可以使用公钥对消息进行加密。但是,对消息解密则需要两种密钥;因此,只有私钥的持有者才能对消息解密。公钥可用来对发送给证书所有者的消息进行加密。只有所有者才能访问私钥,因此,只有所有者才能解密这些消息。

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

有关 证书的更多信息,请参见证书(可能为英文网页)。

查看证书

若要使用证书,通常需要查看证书并检查其属性。使用 Microsoft 管理控制台 (MMC) 管理单元工具,很容易实现这一任务。有关更多信息,请参见 如何:使用 MMC 管理单元查看证书。有关如何使用此工具的其他文档,请参见 Httpcfg 概述(可能为英文网页)。

证书存储区

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

  • 本地计算机存储区。该存储区包含计算机进程(例如 ASP.NET)访问的证书。此位置用于存储向客户端验证服务器身份的证书。
  • 当前用户存储区。交互式应用程序通常将证书放在此位置,供计算机的当前用户使用。如果要创建客户端应用程序,通常会将向服务验证用户身份的证书放在此处。

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

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

    提示

    本地计算机隐式信任放置在此存储区中的任何证书,即使证书不是来自受信任的第三方证书颁发机构,也是如此。因此,除非完全信任颁发机构并了解后果,否则不要将任何证书放入此存储区。

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

有关 证书存储区的更多信息,请参见证书存储区(可能为英文网页)。

选择存储区

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

  • 如果该服务是 Windows 服务(即在“服务器”模式下运行且在网络服务帐户下没有任何用户界面的服务),则使用**“本地计算机”**存储区。请注意,要将证书安装到本地计算机存储区,需要有管理员权限。
  • 如果在使用用户帐户运行的应用程序中嵌入服务或客户端,则使用**“当前用户”**存储区。

访问存储区

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

链信任和证书颁发机构

数字证书通过信任链对实体进行身份验证。信任链是自上而下形成的,根颁发机构在最顶端。在 MMC 管理单元中,双击任何证书,再单击**“证书路径”选项卡,可以查看任何证书链。证书链顶端的根颁发机构证书是自行颁发的。也就是说,颁发机构即是要向其颁发证书的实体。有关 导入证书颁发机构的证书链的更多信息,请参见如何:指定用于验证签名的证书颁发机构证书链 (WCF)

提示

通过将颁发机构的证书放入受信任的根颁发机构证书存储区中,可以向任何颁发机构指定受信任的根颁发机构。

禁用链信任

在创建新服务时,可能会使用不是由受信任的根证书颁发的证书,或者颁发证书本身可能不在受信任的根证书颁发机构存储区中。如果仅为了开发目的,可以暂时禁用检查证书信任链的机制。为此,需要将 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 Certificate Validator示例。有关更多信息,请参见 自定义凭据和凭据验证

使用 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> Element(在 serviceBehaviors 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 方法设置用于向客户端验证服务身份的服务证书。

具有相同值的多个证书

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

配置中的证书

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

将证书映射到用户帐户

IIS 和 Active Directory 的一个功能是将证书映射到 Windows 用户帐户。有关 此功能的更多信息,请参见将证书映射到用户帐户(可能为英文网页)。

有关 使用 Active Directory 映射的更多信息,请参见使用目录服务映射来映射客户端证书(可能为英文网页)。

如果启用了这一功能,则可以将 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

其他资源

保护服务和客户端的安全