Share via


HOW TO:使用 Windows 認證來確保服務安全

這個主題會示範如何針對位於 Windows 網域中,而且是由相同網域中的用戶端所呼叫的 Windows Communication Foundation (WCF) 服務,啟用其上面的傳輸安全性。如需詳細資訊此案例的詳細資訊,請參閱Windows 驗證的傳輸安全性。如需範例應用程式,請參閱 WSHttpBinding 範例。

這個主題假設您擁有現有的合約介面、已定義了實作 (Implementation),以及一些附加內容。您也可以修改現有的服務和用戶端。

您可以完全使用程式碼,透過 Windows 認證來確保服務安全。或者,您也可以使用組態檔來省略部分程式碼。這個主題會說明這兩種方式。請務必只使用其中一種方式,不要兩種都使用。

前三個程序會說明如何使用程式碼來保護服務安全。第四和第五個程序會說明如何使用組態檔來執行這項作業。

使用程式碼

服務和用戶端的完整程式碼已提供於本主題結尾的「範例」一節。

第一個程序會逐步解說如何使用程式碼建立和設定 WSHttpBinding 類別。繫結會使用 HTTP 傳輸。用戶端上會使用相同的繫結。

建立會使用 Windows 認證和訊息安全性的 WSHttpBinding

  1. 這個程序的程式碼會插入至「範例」一節服務程式碼中 Test 類別的 Run 方法開頭。

  2. 建立 WSHttpBinding 類別的執行個體。

  3. WsHttpSecurity 類別的 Mode 屬性設定為 Message

  4. MessageSecurityOverHttp 類別的 ClientCredentialType 屬性設定為 Windows

  5. 這項程序的程式碼如下所示:

    Dim myBinding As New WSHttpBinding()
    myBinding.Security.Mode = SecurityMode.Message
    myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows
    
    // 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;
    

在服務中使用繫結

這是第二個程序,說明如何在自我裝載的服務中使用繫結。如需詳細資訊裝載服務的詳細資訊,請參閱裝載服務

在服務中使用繫結

  1. 將這個程序的程式碼插入到前一個程序的程式碼後面。

  2. 建立名稱為 contractTypeType 變數,並將其類型指派為介面 (ICalculator)。使用 Visual Basic 時,請使用 GetType 運算子;使用 C# 時,請使用 typeof 關鍵字。

  3. 建立第二個名稱為 serviceTypeType 變數,並將其類型指派為實作的合約 (Calculator)。

  4. 使用服務的基底位址,建立名稱為 baseAddressUri 類別的執行個體。基底位址必須具有符合傳輸的配置。在這個情況下,傳輸配置為 HTTP,而位址中則包含特殊統一資源識別項 (URI) "localhost"、連接埠號碼 (8036) 和基底端點位址 (serviceModelSamples/):https://localhost:8036/serviceModelSamples/。

  5. 使用 serviceTypebaseAddress 變數,建立 ServiceHost 類別的執行個體。

  6. 使用 contractType、繫結和端點名稱 (secureCalculator),將端點新增至服務。初始化服務的呼叫時,用戶端必須串連基底位址和端點名稱。

  7. 呼叫 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("https://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()
    
    // 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("https://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();
    

在用戶端中使用繫結

這項程序會說明如何產生與服務進行通訊的 Proxy。此 Proxy 是使用 ServiceModel 中繼資料公用程式工具 (Svcutil.exe) 所產生,該工具會使用服務中繼資料建立 Proxy。

此程序還會建立可與服務進行通訊之 WSHttpBinding 類別的執行個體,然後呼叫該服務。

這個範例只會使用程式碼來建立用戶端。或者,您可以使用組態檔,該檔案會在此程序之後的章節中說明。

搭配程式碼在用戶端中使用繫結

  1. 使用 SvcUtil.exe 工具,從服務的中繼資料產生 Proxy 程式碼。如需詳細資訊,請參閱 HOW TO:建立 Windows Communication Foundation 用戶端. 產生的 Proxy 程式碼繼承自 ClientBase 類別,這樣可確保每個用戶端都有與 WCF 服務進行通訊時所需要的建構函式、方法和屬性。在這個範例中,產生的程式碼包含 CalculatorClient 類別,這個類別會實作 ICalculator 介面,因此就會與服務程式碼相容。

  2. 此程序的程式碼會插入至用戶端程式的 Main 方法開頭。

  3. 建立 WSHttpBinding 類別的執行個體,將其安全性模式設定為 Message,並將其用戶端認證類型設定為 Windows。這個範例會將變數命名為 clientBinding

  4. 建立名稱為 serviceAddressEndpointAddress 類別的執行個體。使用與端點名稱串連的基底位址初始化執行個體。

  5. 使用 serviceAddressclientBinding 變數,建立產生之用戶端類別的執行個體。

  6. 呼叫 Open 方法,如下列程式碼所示。

  7. 呼叫服務並顯示結果。

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

使用組態檔

如果不使用程序程式碼建立繫結,您可以改用下面針對組態檔之繫結區段所顯示的程式碼。

如果您尚未定義服務,請參閱設計與實作服務以及設定服務

注意:這個組態程式碼會同時在服務和用戶端組態檔中使用。

使用組態在 Windows 網域的服務上啟用傳輸安全性

  1. <wsHttpBinding> 項目新增至組態檔的 <bindings> 項目區段中。

  2. 將 <binding> 項目新增至 <WSHttpBinding> 項目,並將 configurationName 屬性設定為適用於您應用程式的值。

  3. 新增 <security> 項目,並將 mode 屬性設定為 Message。

  4. 新增 <message> 項目,並將 clientCredentialType 屬性設定為 Windows。

  5. 在服務的組態檔中,將 <bindings> 區段取代為下列程式碼。如果您尚未建立服務組態檔,請參閱使用繫結來設定服務和用戶端

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

在用戶端中使用繫結

此程序會說明如何產生兩個檔案:與服務進行通訊的 Proxy 及組態檔。此外還會說明用戶端程式的變更,也就是用戶端上使用的第三個檔案。

搭配組態在用戶端中使用繫結

  1. 使用 SvcUtil.exe 工具,從服務的中繼資料產生 Proxy 程式碼和組態檔。如需詳細資訊,請參閱 HOW TO:建立 Windows Communication Foundation 用戶端.

  2. 將已產生之組態檔的 <Bindings> 區段取代為前一個區段的組態程式碼。

  3. 程序程式碼會插入至用戶端程式的 Main 方法開頭。

  4. 建立已產生之用戶端類別的執行個體,將組態檔中繫結的名稱當做輸入參數傳遞。

  5. 呼叫 Open 方法,如下列程式碼所示。

  6. 呼叫服務並顯示結果。

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

範例

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("https://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;
        }
    }
}

另請參閱

工作

HOW TO:建立 Windows Communication Foundation 用戶端

參考

WSHttpBinding

概念

ServiceModel 中繼資料公用程式工具 (Svcutil.exe)
保護服務的安全
安全性概觀