如何:使用 SSL 证书配置端口

使用 WSHttpBinding 类(使用传输安全)创建自承载 Windows Communication Foundation (WCF) 服务时,还必须使用 X.509 证书配置端口。 如果不是在创建自承载服务,可以在 Internet 信息服务 (IIS) 上承载服务。 有关详细信息,请参阅 HTTP 传输安全性

若要配置端口,使用的工具取决于计算机运行的操作系统。

如果运行的是 Windows Server 2003,则使用 HttpCfg.exe 工具。 在 Windows Server 2003 上,已安装此工具。 有关详细信息,请参阅 Httpcfg 概述Windows 支持工具文档说明了 Httpcfg.exe 工具的语法。

如果运行的是 Windows Vista,则使用已安装的 Netsh.exe 工具。

注意

修改计算机上存储的证书需要管理权限。

确定如何配置端口

  1. 在 Windows Server 2003 或 Windows XP 中,通过 query 和 ssl 开关使用 HttpCfg.exe 工具查看当前端口配置,如下面的示例所示。

    httpcfg query ssl  
    
  2. 在 Windows Vista 中,使用 Netsh.exe 工具查看当前端口配置,如下面的示例所示。

    netsh http show sslcert  
    

获取证书的指纹

  1. 使用证书 MMC 管理单元查找用于客户端身份验证的 X.509 证书。 有关详细信息,请参阅如何:使用 MMC 管理单元查看证书

  2. 访问证书的指纹。 有关详细信息,请参阅如何:检索证书的指纹

  3. 将证书指纹复制到文本编辑器,如 Notepad。

  4. 移除十六进制字符之间的所有空格。 完成此操作的一种方法是使用文本编辑器的“查找和替换”功能,将每个空格替换为空字符。

将 SSL 证书绑定到端口号

  1. 在 Windows Server 2003 或 Windows XP 中,在“set”模式下在安全套接字层 (SSL) 存储上使用 HttpCfg.exe 工具,将证书绑定至端口号。 该工具使用指纹识别证书,如下面的示例所示。

    httpcfg set ssl -i 0.0.0.0:8012 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6  
    
    • -i 开关的语法为 IP:port,指示该工具将证书设置为计算机的端口 8012。 另外,也可将端口号前面的四个零替换为计算机的实际 IP 地址。

    • -h 开关指定证书的指纹。

  2. 在 Windows Vista 中使用 Netsh.exe 工具,如下面的示例所示。

    netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00001111-aaaa-2222-bbbb-3333cccc4444}
    
    • certhash 参数指定证书的指纹。

    • ipport 参数指定 IP 地址和端口,功能类似于前述 Httpcfg.exe 工具的 -i 开关。

    • appid 参数为可用于标识所属应用程序的 GUID。

将 SSL 证书绑定至端口号并支持客户端证书

  1. 在 Windows Server 2003 或 Windows XP 中,若要支持在传输层使用 X.509 证书进行身份验证的客户端,请按照前面的步骤进行操作,但要向 HttpCfg.exe 另外传递一个命令行参数,如下面的示例所示。

    httpcfg set ssl -i 0.0.0.0:8012 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6 -f 2  
    

    -f 开关的语法为 n,其中 n 是介于 1 到 7 之间的一个数字。 值为 2 可在传输层启用客户端证书,如上面的示例所示。 值为 3 可启用客户端证书并将这些证书映射至 Windows 帐户。 请参见“HttpCfg.exe 帮助”以获取其他值的行为。

  2. 在 Windows Vista 中,若要支持在传输层使用 X.509 证书进行身份验证的客户端,请按照前面的步骤进行操作,但要另外提供一个参数,如下面的示例所示。

    netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00001111-aaaa-2222-bbbb-3333cccc4444} clientcertnegotiation=enable  
    

删除端口号的 SSL 证书

  1. 使用 HttpCfg.exe 或 Netsh.exe 工具查看计算机上的端口和所有绑定的指纹。 若要将信息输出到磁盘,请使用重定向字符“>”,如下面的示例所示。

    httpcfg query ssl>myMachinePorts.txt  
    
  2. 在 Windows Server 2003 或 Windows XP 中,将 HttpCfg.exe 工具与 delete 和 ssl 关键字一起使用。 使用 -i 开关指定 IP:port 号,使用 -h 开关指定指纹。

    httpcfg delete ssl -i 0.0.0.0:8005 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6  
    
  3. 在 Windows Vista 中使用 Netsh.exe 工具,如下面的示例所示。

    Netsh http delete sslcert ipport=0.0.0.0:8005  
    

示例

下面的代码演示如何使用 WSHttpBinding 类(设置为传输安全)创建自承载服务。 创建应用程序时,请指定地址中的端口号。

// This string uses a function to prepend the computer name at run time.
string addressHttp = String.Format(
    "http://{0}:8080/Calculator",
    System.Net.Dns.GetHostEntry("").HostName);

WSHttpBinding b = new WSHttpBinding();
b.Security.Mode = SecurityMode.Transport;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;

// You must create an array of URI objects to have a base address.
Uri a = new Uri(addressHttp);
Uri[] baseAddresses = new Uri[] { a };

// Create the ServiceHost. The service type (Calculator) is not
// shown here.
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);

// Add an endpoint to the service. Insert the thumbprint of an X.509
// certificate found on your computer.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyCalculator");
sh.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "contoso.com");

// This next line is optional. It specifies that the client's certificate
// does not have to be issued by a trusted authority, but can be issued
// by a peer if it is in the Trusted People store. Do not use this setting
// for production code. The default is PeerTrust, which specifies that
// the certificate must originate from a trusted certificate authority.

// sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
// X509CertificateValidationMode.PeerOrChainTrust;
try
{
    sh.Open();

    string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
    Console.WriteLine("Listening @ {0}", address);
    Console.WriteLine("Press enter to close the service");
    Console.ReadLine();
    sh.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine("A communication error occurred: {0}", ce.Message);
    Console.WriteLine();
}
catch (System.Exception exc)
{
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message);
    Console.ReadLine();
}
' This string uses a function to prepend the computer name at run time.
Dim addressHttp As String = String.Format("http://{0}:8080/Calculator", _
System.Net.Dns.GetHostEntry("").HostName)

Dim b As New WSHttpBinding()
b.Security.Mode = SecurityMode.Transport
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate

' You must create an array of URI objects to have a base address.
Dim a As New Uri(addressHttp)
Dim baseAddresses() As Uri = {a}

' Create the ServiceHost. The service type (Calculator) is not
' shown here.
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)

' Add an endpoint to the service. Insert the thumbprint of an X.509 
' certificate found on your computer. 
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyCalculator")
sh.Credentials.ServiceCertificate.SetCertificate( _
                StoreLocation.LocalMachine, _
                StoreName.My, _
                X509FindType.FindBySubjectName, _
                "contoso.com")

' This next line is optional. It specifies that the client's certificate
' does not have to be issued by a trusted authority, but can be issued
' by a peer if it is in the Trusted People store. Do not use this setting
' for production code. The default is PeerTrust, which specifies that 
' the certificate must originate from a trusted certificate authority.
' sh.Credentials.ClientCertificate.Authentication.CertificateValidationMode =
' X509CertificateValidationMode.PeerOrChainTrust
Try
    sh.Open()

    Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
    Console.WriteLine("Listening @ {0}", address)
    Console.WriteLine("Press enter to close the service")
    Console.ReadLine()
    sh.Close()
Catch ce As CommunicationException
    Console.WriteLine("A communication error occurred: {0}", ce.Message)
    Console.WriteLine()
Catch exc As System.Exception
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message)
    Console.ReadLine()
End Try

另请参阅