如何:使用 X.509 证书保证服务的安全

使用 X.509 证书保护服务的安全是一项基本技术,Windows Communication Foundation (WCF) 中的大多数绑定均使用此技术。 本主题演练使用 X.509 证书配置自承载服务的步骤。

先决条件是具有可用于对服务器进行身份验证的有效证书。 证书必须由受信任的证书颁发机构颁发给服务器。 如果证书无效,则尝试使用该服务的任何客户端都不会信任该服务,因此不会建立连接。 有关使用证书的详细信息,请参阅使用证书

使用代码用证书配置服务

  1. 创建服务协定和实现的服务。 有关详细信息,请参阅设计和实现服务

  2. 创建 WSHttpBinding 类的一个实例,并将其安全模式设置为 Message,如下面的代码所示。

    // Create a binding and set the security mode to Message.
    WSHttpBinding b = new WSHttpBinding(SecurityMode.Message);
    
    ' Create a binding and set the security mode to Message.
    Dim b As New WSHttpBinding(SecurityMode.Message)
    
  3. 创建两个 Type 变量,分别用于协定类型和实现的协定,如下面的代码所示。

    Type contractType = typeof(ICalculator);
    Type implementedContract = typeof(Calculator);
    
    Dim contractType = GetType(ICalculator)
    Dim implementedContract = GetType(Calculator)
    
  4. 为服务的基址创建 Uri 类的一个实例。 由于 WSHttpBinding 使用 HTTP 传输,因此,统一资源标识符 (URI) 必须以该架构开始,否则打开服务时,Windows Communication Foundation (WCF) 将引发异常。

    Uri baseAddress = new Uri("http://localhost:8044/base");
    
    Dim baseAddress As New Uri("http://localhost:8044/base")
    
  5. 使用实现的协定类型变量和 URI 创建 ServiceHost 类的新实例。

    ServiceHost sh = new ServiceHost(implementedContract, baseAddress);
    
    Dim sh As New ServiceHost(implementedContract, baseAddress)
    
  6. 使用 ServiceEndpoint 方法向服务中添加一个 AddServiceEndpoint。 将协定、绑定和终结点地址传递给构造函数,如下面的代码所示。

    sh.AddServiceEndpoint(contractType, b, "Calculator");
    
    sh.AddServiceEndpoint(contractType, b, "Calculator")
    
  7. 可选。 若要从服务中检索元数据,请创建一个新的 ServiceMetadataBehavior 对象并将 HttpGetEnabled 属性设置为 true

    ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
    sm.HttpGetEnabled = true;
    sh.Description.Behaviors.Add(sm);
    
    Dim sm As New ServiceMetadataBehavior()
    sm.HttpGetEnabled = True
    
    With sh
        .Description.Behaviors.Add(sm)
    
  8. 使用 SetCertificate 类的 X509CertificateRecipientServiceCredential 方法将有效证书添加到服务中。 该方法可以使用多个方法之一查找证书。 本示例使用 FindBySubjectName 枚举。 该枚举指定提供的值是为其颁发证书的实体的名称。

    sh.Credentials.ServiceCertificate.SetCertificate(
        StoreLocation.LocalMachine ,StoreName.My,
        X509FindType.FindBySubjectName ,"localhost");
    
    .Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, _
                                                   StoreName.My, _
                                                   X509FindType.FindBySubjectName, _
                                                   "localhost")
    
  9. 调用 Open 方法以开始服务侦听。 如果您要创建控制台应用程序,请调用 ReadLine 方法以保持服务处于侦听状态。

    sh.Open();
    Console.WriteLine("Listening");
    Console.ReadLine();
    
    .Open()
    Console.WriteLine("Listening")
    Console.ReadLine()
    

示例

下面的示例使用 SetCertificate 方法用 X.509 证书配置服务。

// Create a binding and set the security mode to Message.
WSHttpBinding b = new WSHttpBinding(SecurityMode.Message);

Type contractType = typeof(ICalculator);
Type implementedContract = typeof(Calculator);

Uri baseAddress = new Uri("http://localhost:8044/base");

ServiceHost sh = new ServiceHost(implementedContract, baseAddress);

sh.AddServiceEndpoint(contractType, b, "Calculator");

ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
sm.HttpGetEnabled = true;
sh.Description.Behaviors.Add(sm);

sh.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine ,StoreName.My,
    X509FindType.FindBySubjectName ,"localhost");

sh.Open();
Console.WriteLine("Listening");
Console.ReadLine();
sh.Close();
' Create a binding and set the security mode to Message.
Dim b As New WSHttpBinding(SecurityMode.Message)

Dim contractType = GetType(ICalculator)
Dim implementedContract = GetType(Calculator)

Dim baseAddress As New Uri("http://localhost:8044/base")

Dim sh As New ServiceHost(implementedContract, baseAddress)

sh.AddServiceEndpoint(contractType, b, "Calculator")

Dim sm As New ServiceMetadataBehavior()
sm.HttpGetEnabled = True

With sh
    .Description.Behaviors.Add(sm)

    .Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, _
                                                   StoreName.My, _
                                                   X509FindType.FindBySubjectName, _
                                                   "localhost")

    .Open()
    Console.WriteLine("Listening")
    Console.ReadLine()
    .Close()
End With

编译代码

编译该代码需要以下命名空间:

另请参阅