Vorgehensweise: Sichern eines Dienstes mit Windows-Anmeldeinformationen

In diesem Thema wird gezeigt, wie die Übertragungssicherheit für einen Windows Communication Foundation (WCF)-Dienst in einer Windows-Domäne aktiviert und von Clients in der gleichen Domäne aufgerufen wird. Weitere Informationen finden Sie unterDieses Szenario finden Sie unter Transportsicherheit mit Windows-Authentifizierung. Eine beispielanwendung finden Sie unter der WSHttpBinding Beispiel.

In diesem Thema wird vorausgesetzt, dass Sie über eine vorhandene Vertragsschnittstelle verfügen und die Implementierung bereits definiert wurde, da hier auf diese beiden Punkte aufgebaut wird. Sie können auch einen vorhandenen Dienst und Client ändern.

Sie können einen Dienst mit Windows-Anmeldeinformationen vollständig im Code sichern. Alternativ können Sie bei Verwendung einer Konfigurationsdatei einige Teile des Codes weglassen. In diesem Thema werden beide Methoden gezeigt. Verwenden Sie jedoch stets nur eine der Methoden.

In den ersten drei Prozeduren wird gezeigt, wie der Dienst unter Verwendung von Code gesichert wird. Die vierte und fünfte Prozedur zeigen, wie dies mit einer Konfigurationsdatei erreicht wird.

Mithilfe von Code

Den vollständigen Code für Dienst und Client finden Sie im Beispielabschnitt am Ende dieses Themas.

Die erste Prozedur führt durch Erstellen und Konfigurieren einer WSHttpBinding -Klasse im Code. Für die Bindung wird der HTTP-Transport verwendet. Die gleiche Bindung wird auf dem Client verwendet.

So erstellen Sie eine WSHttpBinding, die Windows-Anmeldeinformationen und Nachrichtensicherheit verwendet

  1. Der Code dieser Prozedur wird im Dienstcode des Beispielabschnitts am Anfang der Run-Methode der Test-Klasse eingefügt.

  2. Erstellen Sie eine Instanz der WSHttpBinding Klasse.

  3. Festlegen der <xref:System.ServiceModel.WsHttpSecurity.Mode%2A> Eigenschaft der <xref:System.ServiceModel.WsHttpSecurity> Klasse SecurityMode.

  4. Festlegen der ClientCredentialType Eigenschaft der MessageSecurityOverHttp Klasse MessageCredentialType.

  5. Für diese Prozedur wird der folgende Code verwendet:

    // First procedure:
    // create a WSHttpBinding that uses Windows credentials and message security
    WSHttpBinding myBinding = new WSHttpBinding();
    myBinding.Security.Mode = SecurityMode.Message;
    myBinding.Security.Message.ClientCredentialType =
        MessageCredentialType.Windows;
    
    Dim myBinding As New WSHttpBinding()
    myBinding.Security.Mode = SecurityMode.Message
    myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
    

Verwenden der Bindung in einem Dienst

Dies ist die zweite Prozedur; in dieser Prozedur wird die Verwendung der Bindung in einem selbst gehosteten Dient veranschaulicht. Weitere Informationen finden Sie unterHosten von Diensten finden Sie unter Hostingdienste.

So verwenden Sie eine Bindung in einem Dienst
  1. Fügen Sie den Code dieser Prozedur nach dem Code der vorherigen Prozedur ein.

  2. Erstellen einer Type Variable mit dem Namen contractType und den Typ der Schnittstelle zuweisen (ICalculator). Verwenden Sie für Visual Basic den Operator GetType und für C# das Schlüsselwort typeof.

  3. Erstellen Sie eine zweite Type-Variable mit der Bezeichnung serviceType, und weisen Sie ihr den Typ des implementierten Vertrags (Calculator) zu.

  4. Erstellen Sie eine Instanz der Uri Klasse mit dem Namen baseAddress mit der Basisadresse des Diensts. Die Basisadresse muss ein Schema haben, das mit dem Transport übereinstimmt. In diesem Fall ist das Transportschema HTTP, und die Adresse enthält den speziellen Uniform Resource Identifier (URI) "localhost" und eine Anschlussnummer (8036) sowie eine Basisendpunktadresse ("serviceModelSamples/): http://localhost:8036/serviceModelSamples/.

  5. Erstellen Sie eine Instanz von der ServiceHost Klasse, wobei die serviceType und baseAddress Variablen.

  6. Fügen Sie dem Dienst einen Endpunkt mit contractType, Bindung und einem Endpunktnamen (secureCalculator) hinzu. Ein Client muss beim Initiieren eines Aufrufs zum Dienst die Basisadresse und den Endpunktnamen verketten.

  7. Rufen Sie die Open Methode, um den Dienst zu starten. Der Code für diese Prozedur wird hier gezeigt:

    // 2nd Procedure:
    // Use the binding in a service
    // Create the Type instances for later use and the URI for 
    // the base address.
    Type contractType = typeof(ICalculator);
    Type serviceType = typeof(Calculator);
    Uri baseAddress = new
        Uri("http://localhost:8036/SecuritySamples/");
    
    // Create the ServiceHost and add an endpoint, then start
    // the service.
    ServiceHost myServiceHost =
        new ServiceHost(serviceType, baseAddress);
    myServiceHost.AddServiceEndpoint
        (contractType, myBinding, "secureCalculator");
    
    //enable metadata
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    myServiceHost.Description.Behaviors.Add(smb);
    
    myServiceHost.Open();
    
    ' Create the Type instances for later use and the URI for 
    ' the base address.
    Dim contractType As Type = GetType(ICalculator)
    Dim serviceType As Type = GetType(Calculator)
    Dim baseAddress As New Uri("http://localhost:8036/serviceModelSamples/")
    
    ' Create the ServiceHost and add an endpoint, then start
    ' the service.
    Dim myServiceHost As New ServiceHost(serviceType, baseAddress)
    myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator")
    myServiceHost.Open()
    

Verwenden der Bindung in einem Client

Diese Prozedur zeigt die Generierung eines Proxys, der mit dem Dienst kommuniziert. Der Proxy wird generiert, mit der ServiceModel Metadata Utility Tool (Svcutil.exe) die Metadaten des Diensts verwendet, um den Proxy zu erstellen.

Diese Prozedur erstellt außerdem eine Instanz der WSHttpBinding Klasse, um die Kommunikation mit dem Dienst, und ruft dann den Dienst.

In diesem Beispiel wird zum Erstellen des Clients nur Code verwendet. Alternativ können Sie eine Konfigurationsdatei verwenden. Dies wird im Abschnitt nach dieser Prozedur veranschaulicht.

So verwenden Sie eine Bindung in einem Client mit Code
  1. Verwenden Sie das SvcUtil.exe-Tool, um den Proxycode aus den Metadaten des Diensts zu generieren. Weitere Informationen finden Sie unterGewusst wie: Erstellen eines Clients. Der generierte Proxycode erbt von der ClientBase<TChannel> -Klasse, die stellt sicher, dass alle Clients die erforderlichen Konstruktoren, Methoden und Eigenschaften für die Kommunikation mit einem WCF Service. In diesem Beispiel enthält der generierte Code die CalculatorClient-Klasse, die die ICalculator-Schnittstelle für die Kompatibilität mit dem Dienstcode implementiert.

  2. Der Code dieser Prozedur wird am Anfang der Main-Methode des Clientprogramms eingefügt.

  3. Erstellen Sie eine Instanz der WSHttpBinding -Klasse und legen Sie deren Sicherheitsmodus auf Message und den Typ der Clientanmeldeinformationen Windows. Im Beispiel wird die Variable clientBinding genannt.

  4. Erstellen Sie eine Instanz der EndpointAddress Klasse mit dem Namen serviceAddress. Initialisieren Sie die Instanz mit der mit dem Endpunktnamen verketteten Basisadresse.

  5. Erstellen Sie eine Instanz der generierten Clientklasse mit der serviceAddress-Variablen und der clientBinding-Variablen.

  6. Rufen Sie die Open Methode, wie im folgenden Code gezeigt.

  7. Rufen Sie den Dienst auf, und zeigen Sie die Ergebnisse an.

    // 3rd Procedure:
    //  Creating a binding and using it in a service
    
    // To run using config, comment the following lines, and uncomment out the code
    // following this section
    WSHttpBinding b = new WSHttpBinding(SecurityMode.Message);
    b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
    
    EndpointAddress ea = new EndpointAddress("Http://localhost:8036/SecuritySamples/secureCalculator");
    CalculatorClient cc = new CalculatorClient(b, ea);
    cc.Open();
    
    // Now call the service and display the results
    // Call the Add service operation.
    double value1 = 100.00D;
    double value2 = 15.99D;
    double result = cc.Add(value1, value2);
    Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
    
    // Closing the client gracefully closes the connection and cleans up resources.
    cc.Close();
    
    Dim b As New WSHttpBinding(SecurityMode.Message)
    b.Security.Message.ClientCredentialType = MessageCredentialType.Windows
    
    Dim ea As New EndpointAddress("net.tcp://machinename:8036/endpoint")
    Dim cc As New CalculatorClient(b, ea)
    cc.Open()
    
    ' Alternatively, use a binding name from a configuration file generated by the
    ' SvcUtil.exe tool to create the client. Omit the binding and endpoint address 
    ' because that information is provided by the configuration file.
    ' CalculatorClass cc = new CalculatorClient("ICalculator_Binding")
    

Verwenden der Konfigurationsdatei

Anstelle der Erstellung der Bindung mithilfe von prozeduralem Code können Sie auch den folgenden Code für den Bindungsabschnitt der Konfigurationsdatei verwenden.

Wenn Sie bereits einen Dienst definiert keinen, finden Sie unter entwerfen und Implementieren von Diensten, und Konfigurieren von Diensten.

Hinweis dieser Konfigurationscode wird in den Dienst und die Client-Konfigurationsdateien verwendet.

So aktivieren Sie mit der Konfiguration Übertragungssicherheit für einen Dienst in einer Windows-Domäne

  1. Hinzufügen einer <> > Element der <> > Element-Abschnitt der Konfigurationsdatei.

  2. Fügen Sie dem <binding>-Element ein <WSHttpBinding>-Element hinzu, und legen Sie das configurationName-Attribut auf einen für Ihre Anwendung geeigneten Wert fest.

  3. Fügen Sie ein <security>-Element hinzu, und legen Sie das mode-Attribut auf "Message" fest.

  4. Fügen Sie ein <message>-Element hinzu, und legen Sie das clientCredentialType-Attribut auf "Windows" fest.

  5. Ersetzen Sie in der Konfigurationsdatei des Diensts den <bindings>-Abschnitt durch den folgenden Code. Wenn Sie nicht bereits über eine Dienstkonfigurationsdatei verfügen, finden Sie unter Verwendung von Bindungen für Dienste konfigurieren und Clients.

    <bindings>  
      <wsHttpBinding>  
       <binding name = "wsHttpBinding_Calculator">  
         <security mode="Message">  
           <message clientCredentialType="Windows"/>  
         </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
    

Verwenden der Bindung in einem Client

In dieser Prozedur wird die Generierung zweier Dateien veranschaulicht: einem Proxy, der mit dem Dienst kommuniziert, und einer Konfigurationsdatei. Darüber hinaus werden auch Änderungen am Clientprogramm beschrieben – der dritten Datei, die auf dem Client verwendet wird.

So verwenden Sie eine Bindung für einen Client mit Konfiguration
  1. Verwenden Sie das SvcUtil.exe-Tool, um den Proxycode und die Konfigurationsdatei aus den Metadaten des Diensts zu generieren. Weitere Informationen finden Sie unterGewusst wie: Erstellen eines Clients.

  2. Ersetzen Sie die <> > Abschnitt der generierten Konfigurationsdatei durch den Konfigurationscode aus dem vorherigen Abschnitt.

  3. Prozeduraler Code wird am Anfang der Main-Methode des Clientprogramms eingefügt.

  4. Erstellen Sie eine Instanz der generierten Clientklasse, und geben Sie den Namen der Bindung in der Konfigurationsdatei als Eingabeparameter weiter.

  5. Rufen Sie die Open Methode, wie im folgenden Code gezeigt.

  6. Rufen Sie den Dienst auf, und zeigen Sie die Ergebnisse an.

    // 4th Procedure:
    //  Using config instead of the binding-related code
    // In this case, use a binding name from a configuration file generated by the
    // SvcUtil.exe tool to create the client. Omit the binding and endpoint address 
    // because that information is provided by the configuration file.
    
    CalculatorClient cc = new CalculatorClient("ICalculator_Binding");
    cc.Open();
    
    // Now call the service and display the results
    // Call the Add service operation.
    double value1 = 100.00D;
    double value2 = 15.99D;
    double result = cc.Add(value1, value2);
    Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
    
    // Closing the client gracefully closes the connection and cleans up resources.
    cc.Close();
    

Beispiel

using System;
using System.Collections;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Security.Permissions;

[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
namespace Microsoft.Security.Samples
{
    public class Test
    {
        static void Main()
        {
            Test t = new Test();
            Console.WriteLine("Starting....");
            t.Run();

        }

        private void Run()
        {
            // First procedure:
            // create a WSHttpBinding that uses Windows credentials and message security
            WSHttpBinding myBinding = new WSHttpBinding();
            myBinding.Security.Mode = SecurityMode.Message;
            myBinding.Security.Message.ClientCredentialType =
                MessageCredentialType.Windows;

            // 2nd Procedure:
            // Use the binding in a service
            // Create the Type instances for later use and the URI for 
            // the base address.
            Type contractType = typeof(ICalculator);
            Type serviceType = typeof(Calculator);
            Uri baseAddress = new
                Uri("http://localhost:8036/SecuritySamples/");

            // Create the ServiceHost and add an endpoint, then start
            // the service.
            ServiceHost myServiceHost =
                new ServiceHost(serviceType, baseAddress);
            myServiceHost.AddServiceEndpoint
                (contractType, myBinding, "secureCalculator");

            //enable metadata
            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            myServiceHost.Description.Behaviors.Add(smb);

            myServiceHost.Open();
            Console.WriteLine("Listening");
            Console.WriteLine("Press Enter to close the service");
            Console.ReadLine();
            myServiceHost.Close();
        }
    }

    [ServiceContract]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double a, double b);
    }

    public class Calculator : ICalculator
    {
        public double Add(double a, double b)
        {
            return a + b;
        }
    }
}
using System;
using System.Collections.Generic;
using System.ServiceModel;

namespace Client
{
    static class SecureClientCode
    {
        static void Main()
        {
            // 3rd Procedure:
            //  Creating a binding and using it in a service

            // To run using config, comment the following lines, and uncomment out the code
            // following this section
            WSHttpBinding b = new WSHttpBinding(SecurityMode.Message);
            b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
            
            EndpointAddress ea = new EndpointAddress("Http://localhost:8036/SecuritySamples/secureCalculator");
            CalculatorClient cc = new CalculatorClient(b, ea);
            cc.Open();

            // Now call the service and display the results
            // Call the Add service operation.
            double value1 = 100.00D;
            double value2 = 15.99D;
            double result = cc.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

            // Closing the client gracefully closes the connection and cleans up resources.
            cc.Close();
        }

        static void Main2()
        {
            // 4th Procedure:
            //  Using config instead of the binding-related code
            // In this case, use a binding name from a configuration file generated by the
            // SvcUtil.exe tool to create the client. Omit the binding and endpoint address 
            // because that information is provided by the configuration file.

            CalculatorClient cc = new CalculatorClient("ICalculator_Binding");
            cc.Open();

            // Now call the service and display the results
            // Call the Add service operation.
            double value1 = 100.00D;
            double value2 = 15.99D;
            double result = cc.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

            // Closing the client gracefully closes the connection and cleans up resources.
            cc.Close();
        }
    }


    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples", ConfigurationName = "ICalculator")]
    public interface ICalculator
    {

        [System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")]
        double Add(double n1, double n2);

        [System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")]
        double Subtract(double n1, double n2);

        [System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")]
        double Multiply(double n1, double n2);

        [System.ServiceModel.OperationContractAttribute(Action = "http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction = "http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")]
        double Divide(double n1, double n2);
    }

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public interface ICalculatorChannel : ICalculator, System.ServiceModel.IClientChannel
    {
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public class CalculatorClient : System.ServiceModel.ClientBase<ICalculator>, ICalculator
    {

        public CalculatorClient()
        {
        }

        public CalculatorClient(string endpointConfigurationName)
            :
                base(endpointConfigurationName)
        {
        }

        public CalculatorClient(string endpointConfigurationName, string remoteAddress)
            :
                base(endpointConfigurationName, remoteAddress)
        {
        }

        public CalculatorClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
            :
                base(endpointConfigurationName, remoteAddress)
        {
        }

        public CalculatorClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
            :
                base(binding, remoteAddress)
        {
        }

        public double Add(double n1, double n2)
        {
            return base.Channel.Add(n1, n2);
        }

        public double Subtract(double n1, double n2)
        {
            return base.Channel.Subtract(n1, n2);
        }

        public double Multiply(double n1, double n2)
        {
            return base.Channel.Multiply(n1, n2);
        }

        public double Divide(double n1, double n2)
        {
            return base.Channel.Divide(n1, n2);
        }
    }

}

Siehe auch

WSHttpBinding
ServiceModel Metadata Utility Tool (Svcutil.exe)
Gewusst wie: Erstellen eines Clients
Sichern von Diensten
Übersicht über die Sicherheit