Share via


Nachrichtensicherheit durch gegenseitige Zertifikate

Das folgende Szenario zeigt einen Windows Communication Foundation (WCF) Dienst und einen Client, die mit dem Nachrichten-Sicherheitsmodus gesichert sind. Sowohl der Client als auch der Dienst werden mit Zertifikaten authentifiziert.

Dieses Szenario ist interoperabel, da es WS-Sicherheit mit dem X.509-Zertifikatstokenprofil verwendet.

Hinweis

Dieses Szenario führt keine Aushandlung für das Dienstzertifikat aus. Das Dienstzertifikat muss dem Client vor jeder Kommunikation bereitgestellt werden. Das Serverzertifikat kann mit der Anwendung oder im Rahmen einer Out-of-Band-Kommunikation bereitgestellt werden.

Message security with mutual certificates

Merkmal Beschreibung
Sicherheitsmodus `Message`
Interoperabilität Ja, mit WS-Sicherheit und X.509-Zertifikatstokenprofil kompatible Clients und Dienste.
Authentication Gegenseitige Authentifizierung des Servers und des Clients.
Integrität Ja
Vertraulichkeit Ja
Transport HTTP
Bindung WSHttpBinding

Dienst

Der folgende Code und die folgende Konfiguration werden unabhängig voneinander ausgeführt. Führen Sie eines der folgenden Verfahren aus:

  • Erstellen Sie einen separaten Dienst, indem Sie den Code ohne Konfiguration verwenden.

  • Erstellen Sie mit der angegebenen Konfiguration einen Dienst, aber definieren Sie keine Endpunkte.

Code

Im folgenden Code wird gezeigt, wie ein Dienstendpunkt, der Nachrichtensicherheit verwendet, erstellt wird. Der Dienst benötigt ein Zertifikat, um sich zu authentifizieren.

// Create the binding.
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType =
    MessageCredentialType.Certificate;
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;

// Create the URI for the endpoint.
Uri httpUri = new Uri("http://localhost/Calculator");

// Create the service host.
ServiceHost myServiceHost =
    new ServiceHost(typeof(Calculator), httpUri);

// Specify a certificate to authenticate the service.
myServiceHost.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "contoso.com");

// Add an endpoint to the service.
myServiceHost.AddServiceEndpoint(typeof(ICalculator), binding, "");

// Open the service.
myServiceHost.Open();
Console.WriteLine("Listening...");
Console.ReadLine();

// Close the service.
myServiceHost.Close();
' Create the binding.
Dim binding As New WSHttpBinding()
binding.Security.Mode = SecurityMode.Message
binding.Security.Message.ClientCredentialType = _
MessageCredentialType.Certificate
binding.Security.Message.NegotiateServiceCredential = False
binding.Security.Message.EstablishSecurityContext = False

' Create the URI for the endpoint.
Dim httpUri As New Uri("http://localhost/Calculator")

' Create the service host.
Dim myServiceHost As New ServiceHost(GetType(ServiceModel.Calculator), httpUri)

' Specify a certificate to authenticate the service.
myServiceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, _
StoreName.My, X509FindType.FindBySubjectName, "contoso.com")

' Add an endpoint to the service.
myServiceHost.AddServiceEndpoint(GetType(ICalculator), binding, "")

' Open the service.
myServiceHost.Open()
Console.WriteLine("Listening...")
Console.ReadLine()

' Close the service.
myServiceHost.Close()

Konfiguration

Die folgende Konfiguration kann statt des Codes verwendet werden, um denselben Dienst einzurichten.

<?xml version="1.0" encoding="utf-8"?>  
<configuration>  
  <system.serviceModel>  
    <behaviors>  
      <serviceBehaviors>  
        <behavior name="serviceCredentialBehavior">  
          <serviceCredentials>  
            <serviceCertificate findValue="Contoso.com"
                                storeLocation="LocalMachine"  
                                storeName="My"
                                x509FindType="FindBySubjectName" />  
          </serviceCredentials>  
        </behavior>  
      </serviceBehaviors>  
    </behaviors>  
    <services>  
      <service behaviorConfiguration="serviceCredentialBehavior"
               name="ServiceModel.Calculator">  
        <endpoint address="http://localhost/Calculator"
                  binding="wsHttpBinding"  
                  bindingConfiguration="InteropCertificateBinding"  
                  name="WSHttpBinding_ICalculator"  
                  contract="ServiceModel.ICalculator" />  
      </service>  
    </services>  
    <bindings>  
      <wsHttpBinding>  
        <binding name="InteropCertificateBinding">  
          <security mode="Message">  
            <message clientCredentialType="Certificate"  
                     negotiateServiceCredential="false"  
                     establishSecurityContext="false" />  
          </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
    <client />  
  </system.serviceModel>  
</configuration>  

Client

Der folgende Code und die folgende Konfiguration werden unabhängig voneinander ausgeführt. Führen Sie eines der folgenden Verfahren aus:

  • Erstellen Sie mit dem Code (und Clientcode) einen eigenständigen Client.

  • Erstellen Sie einen Client, der keine Endpunktadressen definiert. Verwenden Sie stattdessen den Clientkonstruktor, der den Konfigurationsnamen als Argument verwendet. Zum Beispiel:

    CalculatorClient cc = new CalculatorClient("EndpointConfigurationName");
    
    Dim cc As New CalculatorClient("EndpointConfigurationName")
    

Code

Der folgende Code erstellt den Client. Der Sicherheitsmodus wird auf "Nachricht" und der Clientanmeldeinformationstyp wird auf "Zertifikat" eingestellt.

// Create the binding.
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
    MessageCredentialType.Certificate;

// Disable credential negotiation and the establishment of
// a security context.
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;

// Create the endpoint address.
EndpointAddress ea = new
    EndpointAddress("http://machineName/Calculator");

// Create the client.
CalculatorClient cc =
    new CalculatorClient(myBinding, ea);

// Specify a certificate to use for authenticating the client.
cc.ClientCredentials.ClientCertificate.SetCertificate(
    StoreLocation.CurrentUser,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "Cohowinery.com");

// Specify a default certificate for the service.
cc.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
    StoreLocation.CurrentUser,
    StoreName.TrustedPeople,
    X509FindType.FindBySubjectName,
    "Contoso.com");

// Begin using the client.
try
{
    cc.Open();
    Console.WriteLine(cc.Add(200, 1111));
    Console.ReadLine();

    // Close the client.
    cc.Close();
}
' Create the binding.
Dim myBinding As New WSHttpBinding()
myBinding.Security.Mode = SecurityMode.Message
myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate

' Disable credential negotiation and the establishment of
' a security context.
myBinding.Security.Message.NegotiateServiceCredential = False
myBinding.Security.Message.EstablishSecurityContext = False

' Create the endpoint address.
Dim ea As New EndpointAddress("http://localhost/Calculator")

' Create the client.
Dim cc As New CalculatorClient(myBinding, ea)

' Specify a certificate to use for authenticating the client.
cc.ClientCredentials.ClientCertificate.SetCertificate( _
    StoreLocation.CurrentUser, StoreName.My, _
    X509FindType.FindBySubjectName, "Cohowinery.com")

' Specify a default certificate for the service.
cc.ClientCredentials.ServiceCertificate.SetDefaultCertificate( _
    StoreLocation.CurrentUser, StoreName.TrustedPeople, _
    X509FindType.FindBySubjectName, "Contoso.com")

' Begin using the client.
Try
    cc.Open()

    Console.WriteLine(cc.Add(100, 11))
    Console.ReadLine()

    ' Close the client.
    cc.Close()
Catch tex As TimeoutException
    Console.WriteLine(tex.Message)
    cc.Abort()
Catch cex As CommunicationException
    Console.WriteLine(cex.Message)
    cc.Abort()
Finally
    Console.WriteLine("Closed the client")
    Console.ReadLine()
End Try

Konfiguration

Der Client wird wie folgt konfiguriert. Ein Client-Zertifikat muss mit dem Parameter <clientCertificate> angegeben werden. Außerdem wird das Dienstzertifikat mit der Option <defaultCertificate> angegeben.

<?xml version="1.0" encoding="utf-8"?>  
<configuration>  
  <system.serviceModel>  
    <behaviors>  
      <endpointBehaviors>  
        <behavior name="ClientCredentialsBehavior">  
          <clientCredentials>  
            <clientCertificate findValue="Cohowinery.com"
                 storeLocation="CurrentUser"  
                 storeName="My"  
                 x509FindType="FindBySubjectName" />  
            <serviceCertificate>  
              <defaultCertificate findValue="Contoso.com"
                                  storeLocation="CurrentUser"  
                                  storeName="TrustedPeople"  
                                  x509FindType="FindBySubjectName" />  
            </serviceCertificate>  
          </clientCredentials>  
        </behavior>  
      </endpointBehaviors>  
    </behaviors>  
    <bindings>  
      <wsHttpBinding>  
        <binding name="WSHttpBinding_ICalculator" >  
          <security mode="Message">  
            <message clientCredentialType="Certificate"
                     negotiateServiceCredential="false"  
                     establishSecurityContext="false" />  
          </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
    <client>  
      <endpoint address="http://machineName/Calculator"
                behaviorConfiguration="ClientCredentialsBehavior"  
                binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_ICalculator"  
                contract="ICalculator"  
                name="WSHttpBinding_ICalculator">  
        <identity>  
          <certificate encodedValue="Encoded_Value_Not_Shown" />  
        </identity>  
      </endpoint>  
    </client>  
  </system.serviceModel>  
</configuration>  

Siehe auch