消息安全证书

此示例演示如何实现一个应用程序,该应用程序对客户端使用 WS 安全性和 X.509 v3 证书身份验证,并要求使用服务器的 X.509 v3 证书进行服务器身份验证。此示例使用默认设置,以便客户端和服务器之间的所有应用程序消息都经过签名和加密。此示例基于 WSHttpBinding,它由一个客户端控制台程序和一个由 Internet 信息服务 (IIS) 承载的服务库组成。该服务实现定义“请求-答复”通信模式的协定。

提示

本主题的末尾介绍了此示例的设置过程和生成说明。

此示例演示如何使用配置来控制身份验证,以及如何从安全上下文中获取调用方的标识,如下面的示例代码所述。

public class CalculatorService : ICalculator
{
    public string GetCallerIdentity()
    {
        // The client certificate is not mapped to a Windows identity by default.
        // ServiceSecurityContext.PrimaryIdentity is populated based on the information
        // in the certificate that the client used to authenticate itself to the service.
        return ServiceSecurityContext.Current.PrimaryIdentity.Name;
    }
    ...
}

服务公开两个终结点,一个用来与使用配置文件 (Web.config) 定义的服务进行通信,另一个用来使用 WS-MetadataExchange 协议来公开服务的 WSDL 文档。终结点由地址、绑定和协定组成。绑定是使用标准 wsHttpBinding 元素配置的,该元素在默认情况下使用消息安全性。此示例将 clientCredentialType 属性设置为 Certificate 以要求进行客户端身份验证。

<system.serviceModel>
  <services>
    <service name="Microsoft.ServiceModel.Samples.CalculatorService"
             behaviorConfiguration="CalculatorServiceBehavior">
      <!-- Use the base address provided by host. -->
      <endpoint address=""
        binding="wsHttpBinding"
        bindingConfiguration="Binding1" 
        contract="Microsoft.ServiceModel.Samples.ICalculator" />
      <!-- The mex endpoint is exposed at https://localhost/servicemodelsamples/service.svc/mex. -->
      <endpoint address="mex"
                binding="mexHttpBinding"
                contract="IMetadataExchange" />
    </service>
  </services>

  <bindings>
    <wsHttpBinding>
      <!-- 
      This configuration defines the security mode as Message and 
      the clientCredentialType as Certificate.
      -->
      <binding name="Binding1">
        <security mode ="Message">
          <message clientCredentialType="Certificate" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
</system.serviceModel>

此行为指定在客户端向服务进行身份验证时使用服务凭据。服务器证书主题名称是在 serviceCredentials 元素的 findValue 属性中指定的。

<!--For debugging purposes, set the includeExceptionDetailInFaults attribute to true.-->
<behaviors>
  <serviceBehaviors>
    <behavior name="CalculatorServiceBehavior">
      <serviceMetadata httpGetEnabled="True"/>
      <serviceDebug includeExceptionDetailInFaults="False" />
      <!-- 
    The serviceCredentials behavior allows you to define a service certificate.
    A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
    This configuration references the "localhost" certificate installed during the set up instructions.
    -->
      <serviceCredentials>
        <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
        <clientCertificate>
          <!-- 
        Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate 
        is in the user's Trusted People store, then it is trusted without performing a
        validation of the certificate's issuer chain. This setting is used here for convenience so that the 
        sample can be run without having certificates issued by a certificate authority (CA).
        This setting is less secure than the default, ChainTrust. The security implications of this 
        setting should be carefully considered before using PeerOrChainTrust in production code. 
        -->
          <authentication certificateValidationMode="PeerOrChainTrust" />
        </clientCertificate>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

客户端终结点配置由服务终结点的绝对地址、绑定和协定组成。客户端绑定是用相应的安全模式和身份验证模式配置的。在跨计算机方案中运行时,请确保相应地更改服务终结点地址。

<system.serviceModel>
  <client>
    <!-- Use a behavior to configure the client certificate to present to the service. -->
    <endpoint address="https://localhost/servicemodelsamples/service.svc" 
              binding="wsHttpBinding" 
              bindingConfiguration="Binding1" 
              behaviorConfiguration="ClientCertificateBehavior"
              contract="Microsoft.ServiceModel.Samples.ICalculator" />
  </client>

  <bindings>
    <wsHttpBinding>
      <!-- 
        This configuration defines the security mode as Message and 
        the clientCredentialType as Certificate.
        -->
      <binding name="Binding1">
        <security mode ="Message">
          <message clientCredentialType="Certificate" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>

  ...
</system.serviceModel>

客户端实现可以通过配置文件或通过代码来设置要使用的证书。下面的示例演示如何设置要在配置文件中使用的证书。

<system.serviceModel>
  ...
  <behaviors>
    <endpointBehaviors>
      <behavior name="ClientCertificateBehavior">
        <!-- 
      The clientCredentials behavior allows you to define a certificate to present to a service.
      A certificate is used by a client to authenticate itself to the service and provide message integrity.
      This configuration references the "client.com" certificate installed during the setup instructions.
      -->
        <clientCredentials>
          <clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
          <serviceCertificate>
            <!-- 
          Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate 
          is in the user's Trusted People store, then it is trusted without performing a
          validation of the certificate's issuer chain. This setting is used here for convenience so that the 
          sample can be run without having certificates issued by a certificate authority (CA).
          This setting is less secure than the default, ChainTrust. The security implications of this 
          setting should be carefully considered before using PeerOrChainTrust in production code. 
          -->
            <authentication certificateValidationMode="PeerOrChainTrust" />
          </serviceCertificate>
        </clientCredentials>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>

下面的示例演示如何在程序中调用服务。

// Create a client.
CalculatorClient client = new CalculatorClient();

// Call the GetCallerIdentity service operation.
Console.WriteLine(client.GetCallerIdentity());
...
//Closing the client gracefully closes the connection and cleans up resources.
client.Close();

运行示例时,操作请求和响应将显示在客户端控制台窗口中。在客户端窗口中按 Enter 可以关闭客户端。

CN=client.com
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Press <ENTER> to terminate client.

通过运行消息安全示例随附的 Setup.bat 批处理文件,可以用相关的证书将客户端和服务器配置为运行承载应用程序,该应用程序需要基于证书的安全性。该批处理文件可以在三个模式下运行。若要在单计算机下运行,请在命令行中键入 setup.bat;若要在服务模式下运行,请键入 setup.bat service;若要在客户端模式下运行,请键入 setup.bat client。在跨计算机运行示例时,可以使用客户端模式和服务器模式。有关详细信息,请参见本主题末尾的设置过程。下面提供了批处理文件不同节的简要概述,您可以修改这些批处理文件,使其能够在相应的配置中运行:

  • 创建客户端证书。
    批处理文件中的以下行用于创建客户端证书。创建的证书的主题名称中会使用指定的客户端名称。证书存储在 CurrentUser 存储位置下的 My 存储区中。

    echo ************
    echo making client cert
    echo ************
    makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
    
  • 将客户端证书安装到服务器的受信任证书存储区中。
    批处理文件中的以下行将客户端证书复制到服务器的 TrustedPeople 存储中,以使服务器能够做出相关的信任或非信任决定。为了使安装在 TrustedPeople 存储中的证书能够被 Windows Communication Foundation (WCF) 服务信任,必须将客户端证书验证模式设置为 PeerOrChainTrustPeerTrust 值。请参见前面的服务配置示例,了解如何使用配置文件完成此操作。

    echo ************
    echo copying client cert to server's LocalMachine store
    echo ************
    certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople 
    
  • 创建服务器证书。
    Setup.bat 批处理文件中的以下行创建将要使用的服务器证书。

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    

    %SERVER_NAME% 变量指定服务器名称。该证书存储在 LocalMachine 存储区中。如果用服务参数(如 setup.bat service)运行 Setup.bat 批处理文件,则 %SERVER_NAME% 包含 计算机的完全限定域名。否则,则默认为 `` localhost。

  • 将服务器证书安装到客户端的受信任证书存储区中。
    以下行将服务器证书复制到客户端的受信任人存储中。因为客户端系统不隐式信任 Makecert.exe 生成的证书,所以需要执行此步骤。如果已经拥有一个证书,该证书来源于客户端的受信任根证书(例如由 Microsoft 颁发的证书),则不需要执行使用服务器证书填充客户端证书存储区这一步骤。

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
    
  • 授予对证书私钥的权限。
    Setup.bat 文件中的以下行使存储在 LocalMachine 存储中的服务器证书可以供 ASP.NET 工作进程帐户访问。

    echo ************
    echo setting privileges on server certificates
    echo ************
    for /F "delims=" %%i in ('"%ProgramFiles%\ServiceModelSampleTools\FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i
    set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE
    (ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET
    echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R
    iisreset
    

    提示

    如果您使用的是非美国英文版本的 Microsoft Windows,则必须编辑 Setup.bat 文件,并用与您所在的区域对应的帐户名称替换“NT AUTHORITY\NETWORK SERVICE”帐户名称。

提示

该批处理文件中使用的工具位于 C:\Program Files\Microsoft Visual Studio 8\Common7\tools 或 C:\Program Files\Microsoft SDKs\Windows\v6.0\bin 中。这两个目录中必须有一个位于系统路径中。如果您安装了 Visual Studio,则在您的路径中进入该目录的最简便方法就是打开 Visual Studio 命令提示。转至“开始”按钮,依次选择“所有程序”、“Visual Studio 2005”和“工具”。此命令提示中已经配置了相应的路径。否则,您必须向路径中手动添加相应的目录。

设置、生成和运行示例

  1. 请确保已经执行了 Windows Communication Foundation 示例的一次性安装过程

  2. 若要生成 C# 或 Visual Basic .NET 版本的解决方案,请按照生成 Windows Communication Foundation 示例中的说明进行操作。

在同一计算机上运行示例

  1. 请确保路径包括 Makecert.exe 和 FindPrivateKey.exe 所在的文件夹。

  2. 运行示例安装文件夹中的 Setup.bat。这将安装运行示例所需的所有证书。

    提示

    Setup.bat 批处理文件设计为通过 Windows SDK 命令提示运行。这要求 MSSDK 环境变量指向 SDK 的安装目录。将在 Windows SDK 命令提示中自动设置此环境变量。

  3. 通过在浏览器中输入地址 https://localhost/servicemodelsamples/service.svc 来验证是否对服务具有访问权限。

  4. 启动 \client\bin 中的 Client.exe。客户端活动将显示在客户端控制台应用程序上。

  5. 如果客户端与服务无法进行通信,请参见疑难解答指南

跨计算机运行示例

  1. 在服务计算机上创建目录。使用 Internet 信息服务 (IIS) 管理工具为此目录创建名为 servicemodelsamples 的虚拟应用程序。

  2. 将服务程序文件从 \inetpub\wwwroot\servicemodelsamples 复制到服务计算机上的虚拟目录中。确保复制 \bin 子目录中的文件。另外,将 Setup.bat、Cleanup.bat 和 ImportClientCert.bat 文件复制到服务计算机上。

  3. 在客户端计算机上为这些客户端二进制文件创建一个目录。

  4. 将客户端程序文件复制到客户端计算机上的客户端目录中。另外,将 Setup.bat、Cleanup.bat 和 ImportServiceCert.bat 文件复制到客户端上。

  5. 在服务器上运行 setup.bat service。如果采用 service 参数运行 setup.bat,则使用计算机的完全限定域名创建一个服务证书,并将此服务证书导出到名为 Service.cer 的文件中。

  6. (在 serviceCertificate element of serviceCredentialsfindValue 属性中)编辑 Web.config 以反映新的证书名称,该名称与计算机的完全限定域名相同。

  7. 将服务目录中的 Service.cer 文件复制到客户端计算机上的客户端目录中。

  8. 在客户端上,运行 setup.bat client。如果使用 client 参数运行 setup.bat,则会创建一个名为 client.com 的客户端证书,并将此客户端证书导出到名为 Client.cer 的文件中。

  9. 在客户端计算机上的 Client.exe.config 文件中,更改终结点的地址值,使其与服务的新地址相匹配。通过用服务器的完全限定域名替换 localhost 来执行此操作。

  10. 将客户端目录中的 Client.cer 文件复制到服务器上的服务目录中。

  11. 在客户端上,运行 ImportServiceCert.bat。这会将 Service.cer 文件中的服务证书导入 CurrentUser – TrustedPeople 存储区。

  12. 在服务器上,运行 ImportClientCert.bat,这会将 Client.cer 文件中的客户端证书导入 LocalMachine - TrustedPeople 存储区。

  13. 在客户端计算机上,从命令提示符窗口中启动 Client.exe。如果客户端与服务无法进行通信,请参见疑难解答指南

运行示例后进行清除

  • 运行完示例后运行示例文件夹中的 Cleanup.bat。

    提示

    此脚本不会在跨计算机运行此示例时移除客户端上的服务证书。如果已跨计算机运行使用证书的 Windows Communication Foundation (WCF) 示例,请确保清除已安装在 CurrentUser - TrustedPeople 存储区中的服务证书。为此,请使用以下命令:certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>,例如:certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.