다음을 통해 공유


How to: Secure a Service with Windows Credentials

This topic shows how to enable transfer security on a Windows Communication Foundation (WCF) service that resides in a Windows domain and is called by clients in the same domain. For more information about this scenario, see Transport Security with Windows Authentication. For a sample application, see the WSHttpBinding sample.

This topic assumes you have an existing contract interface and implementation already defined, and adds on to that. You can also modify an existing service and client.

You can secure a service with Windows credentials completely in code. Alternatively, you can omit some of the code by using a configuration file. This topic shows both ways. Be sure you only use one of the ways, not both.

The first three procedures show how to secure the service using code. The fourth and fifth procedure shows how to do it with a configuration file.

Using Code

The complete code for the service and the client is in the Example section at the end of this topic.

The first procedure walks through creating and configuring a WSHttpBinding class in code. The binding uses the HTTP transport. The same binding is used on the client.

To create a WSHttpBinding that uses Windows credentials and message security

  1. This procedure's code is inserted at the beginning of the Run method of the Test class in the service code in the Example section.

  2. Create an instance of the WSHttpBinding class.

  3. Set the Mode property of the WsHttpSecurity class to Message.

  4. Set the ClientCredentialType property of the MessageSecurityOverHttp class to Windows.

  5. The code for this procedure is as follows:

    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;
    

Using the Binding in a Service

This is the second procedure, which shows how to use the binding in a self-hosted service. For more information about hosting services see Hosting Windows Communication Foundation Services.

To use a binding in a service

  1. Insert this procedure's code after the code from the preceding procedure.

  2. Create a Type variable named contractType and assign it the type of the interface (ICalculator). When using Visual Basic, use the GetType operator; when using C#, use the typeof keyword.

  3. Create a second Type variable named serviceType and assign it the type of the implemented contract (Calculator).

  4. Create an instance of the Uri class named baseAddress with the base address of the service. The base address must have a scheme that matches the transport. In this case, the transport scheme is HTTP, and the address includes the special Uniform Resource Identifier (URI) "localhost" and a port number (8036) as well as a base endpoint address ("serviceModelSamples/): https://localhost:8036/serviceModelSamples/.

  5. Create an instance of the ServiceHost class with the serviceType and baseAddress variables.

  6. Add an endpoint to the service using the contractType, binding, and an endpoint name (secureCalculator). A client must concatenate the base address and the endpoint name when initiating a call to the service.

  7. Call the Open method to start the service. The code for this procedure is shown here:

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

Using the Binding in a Client

This procedure shows how to generate a proxy that communicates with the service. The proxy is generated with the ServiceModel Metadata Utility Tool (Svcutil.exe) which uses the service metadata to create the proxy.

This procedure also creates an instance of the WSHttpBinding class to communicate with the service, and then calls the service.

This example uses only code to create the client. As an alternative, you can use a configuration file, which is shown in the section following this procedure.

To use a binding in a client with code

  1. Use the SvcUtil.exe tool to generate the proxy code from the service's metadata. For more information, see How to: Create a Windows Communication Foundation Client. The generated proxy code inherits from the ClientBase class, which ensures that every client has the necessary constructors, methods, and properties to communicate with a WCF service. In this example, the generated code includes the CalculatorClient class, which implements the ICalculator interface, enabling compatibility with the service code.

  2. This procedure's code is inserted at the beginning of the Main method of the client program.

  3. Create an instance of the WSHttpBinding class and set its security mode to Message and its client credential type to Windows. The example names the variable clientBinding.

  4. Create an instance of the EndpointAddress class named serviceAddress. Initialize the instance with the base address concatenated with the endpoint name.

  5. Create an instance of the generated client class with the serviceAddress and the clientBinding variables.

  6. Call the Open method, as shown in the following code.

  7. Call the service and display the results.

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

Using the Configuration File

Instead of creating the binding with procedural code, you can use the following code shown for the bindings section of the configuration file.

If you do not already have a service defined, see Designing and Implementing Services, and Configuring Windows Communication Foundation Services.

Note   This configuration code is used in both the service and client configuration files.

To enable transfer security on a service in a Windows domain using configuration

  1. Add a <wsHttpBinding> element to the <bindings> element section of the configuration file.

  2. Add a <binding> element to the <WSHttpBinding> element and set the configurationName attribute to a value appropriate to your application.

  3. Add a <security> element and set the mode attribute to Message.

  4. Add a <message> element and set the clientCredentialType attribute to Windows.

  5. In the service's configuration file, replace the <bindings> section with the following code. If you do not already have a service configuration file, see Using Bindings to Configure Services and Clients.

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

Using the Binding in a Client

This procedure shows how to generate two files: a proxy that communicates with the service and a configuration file. It also describes changes to the client program, which is the third file used on the client.

To use a binding in a client with configuration

  1. Use the SvcUtil.exe tool to generate the proxy code and configuration file from the service's metadata. For more information, see How to: Create a Windows Communication Foundation Client.

  2. Replace the <Bindings> section of the generated configuration file with the configuration code from the preceding section.

  3. Procedural code is inserted at the beginning of the Main method of the client program.

  4. Create an instance of the generated client class passing the name of the binding in the configuration file as an input parameter.

  5. Call the Open method, as shown in the following code.

  6. Call the service and display the results.

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

Example

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;
        }
    }
}

See Also

Tasks

How to: Create a Windows Communication Foundation Client

Reference

WSHttpBinding

Concepts

Securing Services
Security Overview

Other Resources

ServiceModel Metadata Utility Tool (Svcutil.exe)


© 2007 Microsoft Corporation. All rights reserved.
Build Date: 2009-08-07