Aracılığıyla paylaş


Nasıl yapılır: Windows Kimlik Bilgileri ile Bir Hizmeti Güvenli Hale Getirme

Bu konuda, bir Windows etki alanında bulunan ve aynı etki alanındaki istemciler tarafından çağrılan bir Windows Communication Foundation (WCF) hizmetinde aktarım güvenliğinin nasıl etkinleştirileceği gösterilmektedir. Bu senaryo hakkında daha fazla bilgi için bkz . Windows Kimlik Doğrulaması ile Aktarım Güvenliği. Örnek uygulama için bkz . WSHttpBinding örneği.

Bu konu başlığında, zaten tanımlanmış bir sözleşme arabiriminiz ve uygulamanız olduğu varsayılır ve buna eklenir. Ayrıca mevcut bir hizmeti ve istemciyi de değiştirebilirsiniz.

Windows kimlik bilgileriyle bir hizmetin güvenliğini tamamen kod içinde sağlayabilirsiniz. Alternatif olarak, yapılandırma dosyası kullanarak kodun bir bölümünü atlayabilirsiniz. Bu konu her iki yolu da gösterir. Her ikisini birden değil, yalnızca bir yolu kullandığınızdan emin olun.

İlk üç yordam, kodu kullanarak hizmetin güvenliğini sağlamayı gösterir. Dördüncü ve beşinci yordam, yapılandırma dosyasıyla nasıl yapılacağını gösterir.

Kod Kullanma

Hizmet ve istemcinin tam kodu bu konunun sonundaki Örnek bölümündedir.

İlk yordam, kodda sınıf WSHttpBinding oluşturma ve yapılandırma adımlarını gösterir. Bağlama HTTP aktarımını kullanır. İstemcide aynı bağlama kullanılır.

Windows kimlik bilgilerini ve ileti güvenliğini kullanan bir WSHttpBinding oluşturmak için

  1. Bu yordamın kodu, Örnek bölümündeki hizmet kodunda sınıfının yönteminin Test başına Run eklenir.

  2. Öğesinin bir örneğini oluşturur WSHttpBinding sınıfı.

  3. Mode sınıfının özelliğini WSHttpSecurity olarak Messageayarlayın.

  4. ClientCredentialType sınıfının özelliğini MessageSecurityOverHttp olarak Windowsayarlayın.

  5. Bu yordamın kodu aşağıdaki gibidir:

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

Hizmette Bağlamayı Kullanma

Bu, bağlamanın şirket içinde barındırılan bir hizmette nasıl kullanılacağını gösteren ikinci yordamdır. Barındırma hizmetleri hakkında daha fazla bilgi için bkz . Barındırma Hizmetleri.

Hizmette bağlama kullanmak için
  1. Bu yordamın kodunu önceki yordamdaki kodun arkasına ekleyin.

  2. adlı contractType bir Type değişken oluşturun ve arabiriminin türünü ()ICalculator atayın. Visual Basic kullanırken işlecini GetType kullanın; C# kullanırken anahtar sözcüğünü typeof kullanın.

  3. adlı serviceType ikinci Type bir değişken oluşturun ve uygulanan sözleşmenin (Calculator) türünü atayın.

  4. Hizmetin temel adresiyle adlı baseAddress sınıfın bir örneğini Uri oluşturun. Temel adres, aktarımla eşleşen bir şemaya sahip olmalıdır. Bu durumda, aktarım düzeni HTTP'dir ve adres özel Tekdüzen Kaynak Tanımlayıcısı (URI) "localhost" ve bir bağlantı noktası numarası (8036) ile bir temel uç nokta adresi ("serviceModelSamples/): http://localhost:8036/serviceModelSamples/içerir.

  5. ve baseAddress değişkenleriyle sınıfının bir örneğini ServiceHostserviceType oluşturun.

  6. , bağlamasını ve uç nokta adını (secureCalculator) kullanarak contractTypehizmete bir uç nokta ekleyin. İstemci, hizmete çağrı başlatırken temel adresi ve uç nokta adını birleştirmelidir.

  7. Open Hizmeti başlatmak için yöntemini çağırın. Bu yordamın kodu burada gösterilmiştir:

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

İstemcide Bağlamayı Kullanma

Bu yordam, hizmetle iletişim kuran bir ara sunucu oluşturmayı gösterir. Proxy, proxy'yi oluşturmak için hizmet meta verilerini kullanan ServiceModel Meta Veri Yardımcı Programı Aracı (Svcutil.exe) ile oluşturulur.

Bu yordam ayrıca hizmetle iletişim kurmak için sınıfının bir örneğini WSHttpBinding oluşturur ve ardından hizmeti çağırır.

Bu örnekte istemciyi oluşturmak için yalnızca kod kullanılmaktadır. Alternatif olarak, bu yordamın sonraki bölümünde gösterilen bir yapılandırma dosyası kullanabilirsiniz.

İstemcide bir bağlamayı kodla kullanmak için

  1. Hizmetin meta verilerinden ara sunucu kodu oluşturmak için SvcUtil.exe aracını kullanın. Daha fazla bilgi için bkz . Nasıl yapılır: İstemci Oluşturma. Oluşturulan ara sunucu kodu sınıfından ClientBase<TChannel> devralır ve bu sayede her istemcinin bir WCF hizmetiyle iletişim kurmak için gerekli oluşturuculara, yöntemlere ve özelliklere sahip olmasını sağlar. Bu örnekte, oluşturulan kod arabirimi uygulayarak CalculatorClientICalculator hizmet koduyla uyumluluğu sağlayan sınıfını içerir.

  2. Bu yordamın kodu, istemci programının yönteminin başına Main eklenir.

  3. sınıfının bir örneğini WSHttpBinding oluşturun ve güvenlik modunu Message olarak, istemci kimlik bilgisi türünü olarak Windowsayarlayın. Örnek değişkenini clientBindingolarak adlandırın.

  4. adlı serviceAddresssınıfın EndpointAddress bir örneğini oluşturun. Örneği, uç nokta adıyla birleştirilmiş temel adresle başlatın.

  5. ve değişkenleriyle serviceAddress oluşturulan istemci sınıfının bir örneğini clientBinding oluşturun.

  6. Aşağıdaki kodda Open gösterildiği gibi yöntemini çağırın.

  7. Hizmeti çağırın ve sonuçları görüntüleyin.

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

Yapılandırma Dosyasını Kullanma

Yordam koduyla bağlama oluşturmak yerine, yapılandırma dosyasının bağlamalar bölümü için gösterilen aşağıdaki kodu kullanabilirsiniz.

Henüz tanımlanmış bir hizmetiniz yoksa bkz. Hizmetleri Tasarlama ve Uygulama ve Hizmetleri Yapılandırma.

Not

Bu yapılandırma kodu hem hizmet hem de istemci yapılandırma dosyalarında kullanılır.

Yapılandırmayı kullanarak Windows etki alanındaki bir hizmette aktarım güvenliğini etkinleştirmek için

  1. Yapılandırma dosyasının bindings öğesi bölümüne bir <wsHttpBinding>> öğesi ekleyin.<

  2. öğesine bir <binding> öğe><WSHttpBindingekleyin ve özniteliğini uygulamanıza uygun bir değere ayarlayın.configurationName

  3. Bir <security> öğe ekleyin ve özniteliğini mode İleti olarak ayarlayın.

  4. Bir <message> öğe ekleyin ve özniteliğini clientCredentialType Windows olarak ayarlayın.

  5. Hizmetin yapılandırma dosyasında bölümünü <bindings> aşağıdaki kodla değiştirin. Henüz bir hizmet yapılandırma dosyanız yoksa bkz . Hizmetleri ve İstemcileri Yapılandırmak için Bağlamaları Kullanma.

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

İstemcide Bağlamayı Kullanma

Bu yordamda iki dosyanın nasıl oluşturulacağı gösterilmektedir: hizmetle iletişim kuran bir ara sunucu ve bir yapılandırma dosyası. Ayrıca, istemcide kullanılan üçüncü dosya olan istemci programında yapılan değişiklikleri de açıklar.

Yapılandırmaya sahip bir istemcide bağlama kullanmak için

  1. Hizmetin meta verilerinden ara sunucu kodunu ve yapılandırma dosyasını oluşturmak için SvcUtil.exe aracını kullanın. Daha fazla bilgi için bkz . Nasıl yapılır: İstemci Oluşturma.

  2. Oluşturulan yapılandırma dosyasının <bağlamalar> bölümünü önceki bölümde yer alan yapılandırma koduyla değiştirin.

  3. Yordam kodu, istemci programının yönteminin Main başına eklenir.

  4. Yapılandırma dosyasındaki bağlamanın adını giriş parametresi olarak geçirerek oluşturulan istemci sınıfının bir örneğini oluşturun.

  5. Aşağıdaki kodda Open gösterildiği gibi yöntemini çağırın.

  6. Hizmeti çağırın ve sonuçları görüntüleyin.

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

Örnek

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

Ayrıca bkz.