Freigeben über


Programmieren von WCF-Sicherheit

In diesem Thema werden die grundlegenden Programmieraufgaben beschrieben, die zum Erstellen einer sicheren Windows Communication Foundation (WCF)-Anwendung verwendet werden. In diesem Thema werden nur Authentifizierung, Vertraulichkeit und Integrität behandelt, die gemeinsam als Übertragungssicherheit bezeichnet werden. In diesem Thema wird keine Autorisierung behandelt (die Kontrolle des Zugriffs auf Ressourcen oder Dienste); Informationen zur Autorisierung finden Sie unter "Autorisierung".

Hinweis

Eine wertvolle Einführung in Sicherheitskonzepte, insbesondere in Bezug auf WCF, finden Sie in den Lernprogrammen zu Mustern und Vorgehensweisen auf MSDN unter "Szenarien", "Muster" und "Implementierungsleitfaden für Webdienstverbesserungen (Web Services Enhancements, WSE) 3.0".

Die Programmierung der WCF-Sicherheit basiert auf drei Schritten, die folgendes festlegen: den Sicherheitsmodus, einen Clientanmeldeinformationstyp und die Anmeldeinformationswerte. Sie können diese Schritte entweder über Code oder Konfiguration ausführen.

Festlegen des Sicherheitsmodus

Im Folgenden werden die allgemeinen Schritte für die Programmierung mit dem Sicherheitsmodus in WCF erläutert:

  1. Wählen Sie eine der vordefinierten Bindungen aus, die ihren Anwendungsanforderungen entsprechen. Eine Liste der Bindungsoptionen finden Sie unter System-Provided Bindungen. Standardmäßig ist fast jede Bindung sicherheitsfähig. Eine Ausnahme ist die BasicHttpBinding-Klasse (unter Verwendung der Konfiguration: das <basicHttpBinding>).

    Die ausgewählte Bindung bestimmt den Transport. Verwendet beispielsweise WSHttpBinding HTTP als Transport; NetTcpBinding verwendet TCP.

  2. Wählen Sie einen der Sicherheitsmodi für die Bindung aus. Beachten Sie, dass die ausgewählte Bindung die verfügbaren Modusoptionen bestimmt. Beispielsweise lässt die WSDualHttpBinding Transportsicherheit nicht zu (es ist keine Option). Ebenso erlaubt weder die MsmqIntegrationBinding noch die NetNamedPipeBinding Nachrichtensicherheit.

    Sie haben drei Möglichkeiten:

    1. Transport

      Die Transportsicherheit hängt vom Mechanismus ab, den die von Ihnen ausgewählte Bindung verwendet. Wenn Sie z. B. den Sicherheitsmechanismus verwenden WSHttpBinding , handelt es sich um Secure Sockets Layer (SSL) (auch den Mechanismus für das HTTPS-Protokoll). Im Allgemeinen ist der Hauptvorteil der Transportsicherheit, dass es einen guten Durchsatz liefert, unabhängig davon, welchen Transport Sie verwenden. Es hat jedoch zwei Einschränkungen: Der erste besteht darin, dass der Transportmechanismus den Anmeldeinformationstyp bestimmt, der zum Authentifizieren eines Benutzers verwendet wird. Dies ist nur dann ein Nachteil, wenn ein Dienst mit anderen Diensten zusammenarbeiten muss, die unterschiedliche Arten von Anmeldeinformationen erfordern. Das Zweite ist, dass, weil die Sicherheit nicht auf Nachrichtenebene angewendet wird, sie auf einer Hop-by-Hop-Basis und nicht auf einer End-to-End-Basis implementiert wird. Diese Einschränkung ist nur dann ein Problem, wenn der Nachrichtenpfad zwischen Client und Dienst Vermittler umfasst. Weitere Informationen dazu, welcher Transport verwendet werden soll, finden Sie unter Auswählen eines Transports. Weitere Informationen zur Verwendung der Transportsicherheit finden Sie unter Überblick zur Transportsicherheit.

    2. Message

      Nachrichtensicherheit bedeutet, dass jede Nachricht die erforderlichen Kopfzeilen und Daten enthält, um die Nachricht sicher zu halten. Da die Zusammensetzung der Kopfzeilen unterschiedlich ist, können Sie eine beliebige Anzahl von Anmeldeinformationen angeben. Dies wird zu einem Faktor, wenn Sie mit anderen Diensten zusammenarbeiten, die einen bestimmten Anmeldeinformationstyp erfordern, den ein Transportmechanismus nicht bereitstellen kann, oder wenn die Nachricht mit mehr als einem Dienst verwendet werden muss, wobei jeder Dienst einen anderen Anmeldeinformationstyp erfordert.

      Weitere Informationen finden Sie unter Message Security.

    3. TransportWithMessageCredential

      Diese Wahl verwendet die Transportschicht, um die Nachrichtenübertragung zu sichern, während jede Nachricht die umfangreichen Anmeldeinformationen enthält, die andere Dienste benötigen. Dies kombiniert den Leistungsvorteil der Transportsicherheit mit dem umfassenden Berechtigungsvorteil der Nachrichtensicherheit. Dies ist mit den folgenden Bindungen verfügbar: BasicHttpBinding, , WSFederationHttpBinding, NetPeerTcpBindingund WSHttpBinding.

  3. Wenn Sie die Transportsicherheit für HTTP (d. h. HTTPS) verwenden möchten, müssen Sie auch den Host mit einem SSL-Zertifikat konfigurieren und SSL auf einem Port aktivieren. Weitere Informationen finden Sie unter HTTP-Transportsicherheit.

  4. Wenn Sie das WSHttpBinding verwenden und keine sichere Sitzung einrichten müssen, legen Sie die EstablishSecurityContext-Eigenschaft auf false fest.

    Eine sichere Sitzung tritt auf, wenn ein Client und dienst einen Kanal mit einem symmetrischen Schlüssel erstellen (sowohl Client als auch Server verwenden denselben Schlüssel für die Länge einer Unterhaltung, bis das Dialogfeld geschlossen wird).

Festlegen des Clientanmeldeinformationstyps

Wählen Sie wie erforderlich einen Clientanmeldeinformationstyp aus. Weitere Informationen finden Sie unter Auswahl eines Anmeldetyps. Die folgenden Client-Anmeldedatentypen sind verfügbar:

  • Windows

  • Certificate

  • Digest

  • Basic

  • UserName

  • NTLM

  • IssuedToken

Je nach Ihrer Modus-Auswahl müssen Sie den Zugangsdaten-Typ festlegen. Wenn Sie z. B. den wsHttpBinding ausgewählt und den Modus auf "Nachricht" festgelegt haben, können Sie das Attribut des Message-Elements clientCredentialType auch auf einen der folgenden Werte festlegen: None, Windows, UserName, Certificate und IssuedToken, wie im folgenden Konfigurationsbeispiel gezeigt.

<system.serviceModel>  
<bindings>  
  <wsHttpBinding>  
    <binding name="myBinding">  
      <security mode="Message"/>  
      <message clientCredentialType="Windows"/>  
    </binding>
  </wsHttpBinding>
</bindings>  
</system.serviceModel>  

Oder im Code:

WSHttpBinding b = new WSHttpBinding();
b.Name = "myBinding";
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType=MessageCredentialType.Windows;
Dim b As New WSHttpBinding()
b.Name = "myBinding"
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows

Festlegen von Dienstanmeldeinformationswerten

Nachdem Sie einen Dienstanmeldeinformationstyp ausgewählt haben, müssen Sie die tatsächlichen Anmeldeinformationen für den zu verwendenden Dienst und Client festlegen. Im Dienst werden Anmeldeinformationen mithilfe der ServiceCredentials Klasse festgelegt und von der Credentials Eigenschaft der ServiceHostBase Klasse zurückgegeben. Die verwendete Bindung impliziert den Dienstanmeldeinformationstyp, den gewählten Sicherheitsmodus und den Typ der Clientanmeldeinformationen. Der folgende Code legt ein Zertifikat für Dienstanmeldedaten fest.

// Create the binding for an endpoint.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;

// Create the ServiceHost for a calculator.
Uri baseUri = new Uri("net.tcp://MachineName/tcpBase");
Uri[] baseAddresses = new Uri[] { baseUri };
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);

// Add an endpoint using the binding and a new address.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyEndpoint");

// Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "client.com");
try
{
    sh.Open();
    Console.WriteLine("Listening....");
    Console.ReadLine();
    sh.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine($"A communication error occurred: {ce.Message}");
    Console.WriteLine();
}
catch (System.Exception exc)
{
    Console.WriteLine($"An unforeseen error occurred: {exc.Message}");
    Console.ReadLine();
}
' Create the binding for an endpoint.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message

' Create the ServiceHost for a calculator.
Dim baseUri As New Uri("net.tcp://MachineName/tcpBase")
Dim baseAddresses() As Uri = {baseUri}
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)

' Add an endpoint using the binding and a new address.
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyEndpoint")

' Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate( _
                StoreLocation.LocalMachine, _
                StoreName.My, _
                X509FindType.FindBySubjectName, _
                "contoso.com")
Try
    sh.Open()
    Console.WriteLine("Listening....")
    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

Festlegung von Werten für Client-Zugangsdaten

Legen Sie auf dem Client die Werte für die Clientanmeldeinformationen mithilfe der ClientCredentials Klasse fest, die von der ClientCredentials Eigenschaft der ClientBase<TChannel> Klasse bereitgestellt werden. Mit dem folgenden Code wird ein Zertifikat als Anmeldeinformationen auf einem Client mit dem TCP-Protokoll festgelegt.

// Create a NetTcpBinding and set its security properties. The
// security mode is Message, and the client must be authenticated with
// Windows. Therefore the client must be on the same Windows domain.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

// Set a Type variable for use when constructing the endpoint.
Type c = typeof(ICalculator);

// Create a base address for the service.
Uri tcpBaseAddress =
    new Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName");
// The base address is in an array of URI objects.
Uri[] baseAddresses = new Uri[] { tcpBaseAddress };
// Create the ServiceHost with type and base addresses.
ServiceHost sh = new ServiceHost(typeof(CalculatorClient), baseAddresses);

// Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "");
sh.Open();
string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine($"Listening @ {address}");
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
' Create a NetTcpBinding and set its security properties. The
' security mode is Message, and the client must be authenticated with
' Windows. Therefore the client must be on the same Windows domain.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows

' Set a Type variable for use when constructing the endpoint.
Dim c As Type = GetType(ICalculator)

' Create a base address for the service.
Dim tcpBaseAddress As New Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName")
' The base address is in an array of URI objects.
Dim baseAddresses() As Uri = {tcpBaseAddress}
' Create the ServiceHost with type and base addresses.
Dim sh As New ServiceHost(GetType(CalculatorClient), baseAddresses)

' Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "")
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()

Siehe auch