Dela via


Gör så här: Skydda en tjänst med Windows-autentiseringsuppgifter

Det här avsnittet visar hur du aktiverar transportsäkerhet på en WCF-tjänst (Windows Communication Foundation) som finns i en Windows-domän och anropas av klienter i samma domän. Mer information om det här scenariot finns i Transportsäkerhet med Windows-autentisering. Ett exempelprogram finns i exemplet WSHttpBinding .

Det här avsnittet förutsätter att du har ett befintligt kontraktgränssnitt och en implementering som redan har definierats och lägger till det. Du kan också ändra en befintlig tjänst och klient.

Du kan skydda en tjänst med Windows-autentiseringsuppgifter helt i kod. Du kan också utelämna en del av koden med hjälp av en konfigurationsfil. Det här avsnittet visar åt båda hållen. Se till att du bara använder ett av sätten, inte båda.

De tre första procedurerna visar hur du skyddar tjänsten med hjälp av kod. Den fjärde och femte proceduren visar hur du gör det med en konfigurationsfil.

Använda kod

Den fullständiga koden för tjänsten och klienten finns i avsnittet Exempel i slutet av det här avsnittet.

Den första proceduren beskriver hur du skapar och konfigurerar en WSHttpBinding klass i kod. Bindningen använder HTTP-transporten. Samma bindning används på klienten.

Skapa en WSHttpBinding som använder Windows-autentiseringsuppgifter och meddelandesäkerhet

  1. Den här procedurens kod infogas i början av Run -metoden Test för klassen i tjänstkoden i avsnittet Exempel.

  2. Skapa en instans av WSHttpBinding klassen.

  3. Mode Ange egenskapen för WSHttpSecurity klassen till Message.

  4. ClientCredentialType Ange egenskapen för MessageSecurityOverHttp klassen till Windows.

  5. Koden för den här proceduren är följande:

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

Använda bindningen i en tjänst

Det här är den andra proceduren som visar hur du använder bindningen i en lokalt installerad tjänst. Mer information om värdtjänster finns i Värdtjänster.

Så här använder du en bindning i en tjänst
  1. Infoga den här procedurens kod efter koden från föregående procedur.

  2. Skapa en Type variabel med namnet contractType och tilldela den typen av gränssnitt (ICalculator). När du använder Visual Basic använder du operatorn GetType . Använd nyckelordet typeof när du använder C#.

  3. Skapa en andra Type variabel med namnet serviceType och tilldela den typen av det implementerade kontraktet (Calculator).

  4. Skapa en instans av Uri klassen med namnet baseAddress med basadressen för tjänsten. Basadressen måste ha ett schema som matchar transporten. I det här fallet är transportschemat HTTP och adressen innehåller den särskilda URI:n (Uniform Resource Identifier) "localhost" och ett portnummer (8036) samt en basslutpunktsadress ("serviceModelSamples/): http://localhost:8036/serviceModelSamples/.

  5. Skapa en instans av ServiceHost klassen med variablerna serviceType och baseAddress .

  6. Lägg till en slutpunkt i tjänsten med bindningen contractType, och ett slutpunktsnamn (secureCalculator). En klient måste sammanfoga basadressen och slutpunktsnamnet när ett anrop till tjänsten initieras.

  7. Open Anropa metoden för att starta tjänsten. Koden för den här proceduren visas här:

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

Använda bindningen i en klient

Den här proceduren visar hur du genererar en proxy som kommunicerar med tjänsten. Proxyn genereras med ServiceModel Metadata Utility Tool (Svcutil.exe) som använder tjänstens metadata för att skapa proxyn.

Den här proceduren skapar också en instans av WSHttpBinding klassen för att kommunicera med tjänsten och anropar sedan tjänsten.

I det här exemplet används endast kod för att skapa klienten. Alternativt kan du använda en konfigurationsfil som visas i avsnittet som följer den här proceduren.

Så här använder du en bindning i en klient med kod

  1. Använd verktyget SvcUtil.exe för att generera proxykoden från tjänstens metadata. Mer information finns i Så här skapar du en klient. Den genererade proxykoden ärver från ClientBase<TChannel> klassen, vilket säkerställer att varje klient har de konstruktorer, metoder och egenskaper som krävs för att kommunicera med en WCF-tjänst. I det här exemplet innehåller CalculatorClient den genererade koden klassen, som implementerar ICalculator gränssnittet, vilket möjliggör kompatibilitet med tjänstkoden.

  2. Den här procedurens kod infogas i början av Main -metoden för klientprogrammet.

  3. Skapa en instans av WSHttpBinding klassen och ange dess säkerhetsläge till Message och dess klientautentiseringstyp till Windows. I exemplet namnges variabeln clientBinding.

  4. Skapa en instans av EndpointAddress klassen med namnet serviceAddress. Initiera instansen med basadressen sammanfogad med slutpunktsnamnet.

  5. Skapa en instans av den genererade klientklassen med variablerna serviceAddress clientBinding och .

  6. Open Anropa metoden enligt följande kod.

  7. Anropa tjänsten och visa resultatet.

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

Använda konfigurationsfilen

I stället för att skapa bindningen med procedurkod kan du använda följande kod som visas för avsnittet bindningar i konfigurationsfilen.

Om du inte redan har definierat en tjänst kan du läsa Designa och implementera tjänster och Konfigurera tjänster.

Kommentar

Den här konfigurationskoden används i både tjänst- och klientkonfigurationsfilerna.

Aktivera överföringssäkerhet för en tjänst i en Windows-domän med hjälp av konfiguration

  1. Lägg till ett wsHttpBinding-element> i <avsnittet bindningselement> i konfigurationsfilen.<

  2. Lägg till ett <binding> element i elementet <WSHttpBinding> och ange configurationName attributet till ett värde som är lämpligt för ditt program.

  3. Lägg till ett <security> element och ange mode attributet till Meddelande.

  4. Lägg till ett <message> element och ange clientCredentialType attributet till Windows.

  5. I tjänstens konfigurationsfil ersätter du <bindings> avsnittet med följande kod. Om du inte redan har en tjänstkonfigurationsfil kan du läsa Använda bindningar för att konfigurera tjänster och klienter.

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

Använda bindningen i en klient

Den här proceduren visar hur du genererar två filer: en proxy som kommunicerar med tjänsten och en konfigurationsfil. Den beskriver också ändringar i klientprogrammet, vilket är den tredje filen som används på klienten.

Så här använder du en bindning i en klient med konfiguration

  1. Använd verktyget SvcUtil.exe för att generera proxykoden och konfigurationsfilen från tjänstens metadata. Mer information finns i Så här skapar du en klient.

  2. Ersätt bindningsavsnittet <> i den genererade konfigurationsfilen med konfigurationskoden från föregående avsnitt.

  3. Procedurkod infogas i början av Main -metoden för klientprogrammet.

  4. Skapa en instans av den genererade klientklassen som skickar namnet på bindningen i konfigurationsfilen som en indataparameter.

  5. Open Anropa metoden enligt följande kod.

  6. Anropa tjänsten och visa resultatet.

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

Exempel

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

Se även