Udostępnij za pośrednictwem


Instrukcje: Zabezpieczanie usługi za pomocą poświadczeń systemu Windows

W tym temacie przedstawiono sposób włączania zabezpieczeń transportu w usłudze Windows Communication Foundation (WCF), która znajduje się w domenie systemu Windows i jest wywoływana przez klientów w tej samej domenie. Aby uzyskać więcej informacji na temat tego scenariusza, zobacz Transport Security with Windows Authentication (Zabezpieczenia transportu przy użyciu uwierzytelniania systemu Windows). Aby zapoznać się z przykładową aplikacją, zobacz przykład WSHttpBinding .

W tym temacie przyjęto założenie, że masz już zdefiniowany interfejs kontraktu i implementację oraz dodano do tego. Możesz również zmodyfikować istniejącą usługę i klienta.

Usługę można zabezpieczyć za pomocą poświadczeń systemu Windows całkowicie w kodzie. Alternatywnie można pominąć część kodu przy użyciu pliku konfiguracji. W tym temacie przedstawiono oba sposoby. Upewnij się, że używasz tylko jednego ze sposobów, a nie obu.

Pierwsze trzy procedury pokazują, jak zabezpieczyć usługę przy użyciu kodu. Czwarta i piąta procedura pokazuje, jak to zrobić z plikiem konfiguracji.

Korzystanie z kodu

Pełny kod usługi i klient znajduje się w sekcji Przykład na końcu tego tematu.

Pierwsza procedura przeprowadzi cię przez proces tworzenia i konfigurowania WSHttpBinding klasy w kodzie. Powiązanie używa transportu HTTP. To samo powiązanie jest używane na kliencie.

Aby utworzyć usługę WSHttpBinding korzystającą z poświadczeń systemu Windows i zabezpieczeń komunikatów

  1. Kod tej procedury jest wstawiany na początku Run metody Test klasy w kodzie usługi w sekcji Przykład.

  2. Utworzenie wystąpienia WSHttpBinding klasy.

  3. Mode Ustaw właściwość WSHttpSecurity klasy na Message.

  4. ClientCredentialType Ustaw właściwość MessageSecurityOverHttp klasy na Windows.

  5. Kod tej procedury jest następujący:

    // 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
    

Używanie powiązania w usłudze

Jest to druga procedura, która pokazuje, jak używać powiązania w samoobsługowej usłudze. Aby uzyskać więcej informacji na temat usług hostingowych, zobacz Hosting Services.

Aby użyć powiązania w usłudze
  1. Wstaw kod tej procedury po kodzie z poprzedniej procedury.

  2. Utwórz zmienną Type o nazwie contractType i przypisz jej typ interfejsu (ICalculator). W przypadku korzystania z języka Visual Basic użyj GetType operatora ; w przypadku korzystania z języka C#użyj słowa kluczowego typeof .

  3. Utwórz drugą Type zmienną o nazwie serviceType i przypisz jej typ zaimplementowanego kontraktu (Calculator).

  4. Utwórz wystąpienie Uri klasy o nazwie przy użyciu baseAddress podstawowego adresu usługi. Adres podstawowy musi mieć schemat zgodny z transportem. W takim przypadku schemat transportu to HTTP, a adres zawiera specjalny identyfikator URI (URI) "localhost" i numer portu (8036), a także podstawowy adres punktu końcowego ("serviceModelSamples/): http://localhost:8036/serviceModelSamples/.

  5. Utwórz wystąpienie ServiceHost klasy za pomocą serviceType zmiennych i baseAddress .

  6. Dodaj punkt końcowy do usługi przy użyciu nazwy punktu końcowego contractType, powiązania i punktu końcowego (secureCalculator). Klient musi połączyć adres podstawowy i nazwę punktu końcowego podczas inicjowania wywołania usługi.

  7. Wywołaj metodę Open , aby uruchomić usługę. Kod tej procedury jest pokazany tutaj:

    // 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()
    

Używanie powiązania w kliencie

Ta procedura pokazuje, jak wygenerować serwer proxy, który komunikuje się z usługą. Serwer proxy jest generowany za pomocą narzędzia ServiceModel Metadata Tool (Svcutil.exe), który używa metadanych usługi do tworzenia serwera proxy.

Ta procedura tworzy również wystąpienie WSHttpBinding klasy w celu komunikowania się z usługą, a następnie wywołuje usługę.

W tym przykładzie użyto tylko kodu do utworzenia klienta. Alternatywnie możesz użyć pliku konfiguracji pokazanego w sekcji opisanej w tej procedurze.

Aby użyć powiązania w kliencie z kodem

  1. Użyj narzędzia SvcUtil.exe, aby wygenerować kod serwera proxy na podstawie metadanych usługi. Aby uzyskać więcej informacji, zobacz How to: Create a Client (Instrukcje: tworzenie klienta). Wygenerowany kod serwera proxy dziedziczy z ClientBase<TChannel> klasy, co gwarantuje, że każdy klient ma niezbędne konstruktory, metody i właściwości do komunikowania się z usługą WCF. W tym przykładzie wygenerowany kod zawiera klasę CalculatorClient , która implementuje ICalculator interfejs, umożliwiając zgodność z kodem usługi.

  2. Kod tej procedury jest wstawiany na początku Main metody programu klienckiego.

  3. Utwórz wystąpienie WSHttpBinding klasy i ustaw jego tryb zabezpieczeń na Message i jego typ poświadczeń klienta na Windows. Przykład nazywa zmienną clientBinding.

  4. Utwórz wystąpienie EndpointAddress klasy o nazwie serviceAddress. Zainicjuj wystąpienie przy użyciu adresu podstawowego z nazwą punktu końcowego.

  5. Utwórz wystąpienie wygenerowanej klasy klienta za pomocą serviceAddress zmiennych i clientBinding .

  6. Wywołaj metodę Open , jak pokazano w poniższym kodzie.

  7. Wywołaj usługę i wyświetl wyniki.

    // 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")
    

Korzystanie z pliku konfiguracji

Zamiast tworzyć powiązanie za pomocą kodu proceduralnego, możesz użyć następującego kodu pokazanego dla sekcji powiązań pliku konfiguracji.

Jeśli nie masz jeszcze zdefiniowanej usługi, zobacz Projektowanie i implementowanie usług oraz Konfigurowanie usług.

Uwaga

Ten kod konfiguracji jest używany zarówno w plikach konfiguracji usługi, jak i klienta.

Aby włączyć zabezpieczenia transferu w usłudze w domenie systemu Windows przy użyciu konfiguracji

  1. <Dodaj element wsHttpBinding> do <sekcji elementu bindings> pliku konfiguracji.

  2. Dodaj element doWSHttpBinding><elementu i ustaw configurationName atrybut na wartość odpowiednią dla aplikacji.<binding>

  3. <>securityDodaj element i ustaw atrybut na mode Message.

  4. <>messageDodaj element i ustaw clientCredentialType atrybut na Windows.

  5. W pliku konfiguracji usługi zastąp sekcję <bindings> następującym kodem. Jeśli nie masz jeszcze pliku konfiguracji usługi, zobacz Konfigurowanie usług i klientów przy użyciu powiązań.

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

Używanie powiązania w kliencie

Ta procedura przedstawia sposób generowania dwóch plików: serwera proxy komunikującego się z usługą i plikiem konfiguracji. Opisuje również zmiany w programie klienckim, który jest trzecim plikiem używanym na kliencie.

Aby użyć powiązania w kliencie z konfiguracją

  1. Użyj narzędzia SvcUtil.exe, aby wygenerować kod serwera proxy i plik konfiguracji na podstawie metadanych usługi. Aby uzyskać więcej informacji, zobacz How to: Create a Client (Instrukcje: tworzenie klienta).

  2. Zastąp sekcję <powiązań> wygenerowanego pliku konfiguracji kodem konfiguracji z poprzedniej sekcji.

  3. Kod proceduralny jest wstawiany na początku Main metody programu klienckiego.

  4. Utwórz wystąpienie wygenerowanej klasy klienta przekazujące nazwę powiązania w pliku konfiguracji jako parametr wejściowy.

  5. Wywołaj metodę Open , jak pokazano w poniższym kodzie.

  6. Wywołaj usługę i wyświetl wyniki.

    // 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();
    

Przykład

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

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);
        }
    }
}
Imports System.Collections.Generic
Imports System.ServiceModel



Public Class Program

    Shared Sub Main()
        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")
    End Sub
End Class


<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")> _
    Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double

    <System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")> _
    Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double

    <System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")> _
    Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double

    <System.ServiceModel.OperationContractAttribute(Action:="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction:="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")> _
    Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double
End Interface 'ICalculator

<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _
Public Interface ICalculatorChannel
    : Inherits ICalculator, System.ServiceModel.IClientChannel
End Interface 'ICalculatorChannel

<System.Diagnostics.DebuggerStepThroughAttribute(), System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")> _
Public Class CalculatorClient
    Inherits System.ServiceModel.ClientBase(Of ICalculator)
    Implements ICalculator

    Public Sub New()
        '
    End Sub


    Public Sub New(ByVal endpointConfigurationName As String)
        MyBase.New(endpointConfigurationName)

    End Sub


    Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As String)
        MyBase.New(endpointConfigurationName, remoteAddress)

    End Sub


    Public Sub New(ByVal endpointConfigurationName As String, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
        MyBase.New(endpointConfigurationName, remoteAddress)

    End Sub


    Public Sub New(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress)
        MyBase.New(binding, remoteAddress)

    End Sub


    Public Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Add
        Return MyBase.Channel.Add(n1, n2)

    End Function 'Add


    Public Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Subtract
        Return MyBase.Channel.Subtract(n1, n2)

    End Function 'Subtract


    Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Multiply
        Return MyBase.Channel.Multiply(n1, n2)

    End Function 'Multiply


    Public Function Divide(ByVal n1 As Double, ByVal n2 As Double) As Double Implements ICalculator.Divide
        Return MyBase.Channel.Divide(n1, n2)

    End Function 'Divide
End Class

Zobacz też