How to: Secure SOAP Messages Routed Through the WSE SOAP Router

The Web Services Enhancements for Microsoft .NET Framework (WSE) enables developers to specify and enforce security requirements for SOAP messages exchanged between a client and a SOAP router and SOAP messages exchanged between a SOAP router and a Web service.

Security for SOAP messages exchanged between the client and the router and between the router and the Web service must specify an actor attribute other than the empty string (""). To specify the actor attribute for SOAP messages sent from the client to the router, apply a policy to that SOAP message exchange and set the serviceActor attribute on the turnkey security assertion. Likewise, to specify the actor attribute for SOAP messages sent from the router to the Web service, use the serviceActor attribute on the turnkey security assertion.

Note

Establishing a secure conversation is only supported between a client and the Web service when a SOAP router is not used. That is, a policy cannot include a policy assertion with the serviceActor attribute set to a value other then the empty string ("") and the establishSecurityContext attribute set to true.

Security for SOAP responses exchanged between the Web service and the router must specify an actor attribute other than the empty string (""). To set the actor attribute for SOAP responses sent to the router, set the clientActor attribute on the turnkey security assertion. When security isn't needed between the Web service and the router, the actor attribute can remain as the default empty string ("").

To secure SOAP messages sent to and from a SOAP router

  1. In Microsoft® Visual Studio 2005, create an empty web site.

    1. Start Visual Studio 2005.
    2. On the File menu, click New Web Site.
    3. In the New Web Site dialog box, select Empty Web Site.
    4. In the Location box, enter the name of the Web server for the SOAP router.
      The following procedure uses the location https://localhost/RouterService.
    5. Click OK.
  2. Add an App_Code folder to the project.

    1. In Solution Explorer, right-click Add ASP.NET Folder, and then click App_Code.
  3. Add a class that represents the SOAP router to the solution.

    1. In Solution Explorer, right-click App_Code, and then click Add New Item ...
    2. In the Add New Item dialog box, select Class.
    3. In the Name box, enter the name of the class that represents the SOAP router.
      The following procedure names the class RouterWithPolicy.
    4. Click OK.
  4. Add references to the Microsoft.Web.Services3 and System.Web.Services assemblies.

    1. In Solution Explorer, right-click the project, and then select Add Reference.
    2. Click the .NET tab, select Microsoft.Web.Services3 and System.Web.Services and then click OK.
  5. Add Imports or using directives for WSE-related namespaces.

    1. Open the RouterWithPolicy.cs file.

    2. At the top of the file, add the directives as shown in the following code example.

      Imports System
      Imports System.Data
      Imports System.Configuration
      Imports System.Web
      Imports System.Web.Security
      Imports System.Web.UI
      Imports System.Web.UI.WebControls
      Imports System.Web.UI.WebControls.WebParts
      Imports System.Web.UI.HtmlControls
      
      Imports Microsoft.Web.Services3
      Imports Microsoft.Web.Services3.Messaging
      Imports Microsoft.Web.Services3.Design
      
      Imports System.Security.Cryptography.X509Certificates
      
      using System;
      using System.Data;
      using System.Configuration;
      using System.Web;
      using System.Web.Security;
      using System.Web.UI;
      using System.Web.UI.WebControls;
      using System.Web.UI.WebControls.WebParts;
      using System.Web.UI.HtmlControls;
      
      using Microsoft.Web.Services3;
      using Microsoft.Web.Services3.Messaging;
      using Microsoft.Web.Services3.Design;
      using System.Security.Cryptography.X509Certificates;
      
  6. Edit the RoutingWithPolicy class to derive from the SoapHttpRouter class**.**

    Public Class RouterWithPolicy
        Inherits SoapHttpRouter
    
    public class RouterWithPolicy : SoapHttpRouter
    {
    
  7. Define the policy for SOAP messages exchanged between the client and the SOAP router.

    1. Optionally, create a class that defines the policy for SOAP messages exchanged between the client and the SOAP router.
      The policy can be defined in a policy file instead of in a class.
      The following code example defines a policy that uses the custom policy assertion defined in the previous step.

      Public Class RouterPolicy
          Inherits Policy
      
          Public Sub New()
              Dim assertion As New MutualCertificate11Assertion()
      
              assertion.ClientActor = "http://microsoft.web.services3.samples.securerouting/client"
              assertion.ServiceActor = "https://schemas.xmlsoap.org/soap/actor/next"
      
              assertion.ClientX509TokenProvider = New X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient")
              assertion.ServiceX509TokenProvider = New X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer")
      
              Me.Assertions.Add(assertion)
          End Sub 'New
      End Class 'RouterPolicy
      
      public class RouterPolicy : Policy
      {
          public RouterPolicy()
              : base()
          {
              MutualCertificate11Assertion assertion = new MutualCertificate11Assertion();
      
              assertion.ClientActor = "http://microsoft.web.services3.samples.securerouting/client";
              assertion.ServiceActor = "https://schemas.xmlsoap.org/soap/actor/next";
      
              assertion.ClientX509TokenProvider = new X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient");
              assertion.ServiceX509TokenProvider = new X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");
      
              this.Assertions.Add(assertion);
          }  
      }
      
    2. Override the GetRequestPolicy method and specify for the policy for SOAP messages exchanged between the client and the SOAP router.
      The following code example overrides the GetRequestPolicy method and specifies the policy defined previously.

      Protected Overrides Function GetRequestPolicy() As Policy
          Return New RouterPolicy()
      End Function 'GetRequestPolicy
      
      protected override Policy GetRequestPolicy()
      {
          return new RouterPolicy();
      }
      
  8. Define the policy for SOAP messages exchanged between the SOAP router and the Web service.

    1. Optionally, create a class that defines the policy for SOAP messages exchanged between the SOAP router and the Web service.
      The policy can be defined in a policy file instead of in a class.

    2. Override the GetForwardRequestPolicy method and specify for the policy for SOAP messages exchanged between the client and the SOAP router.
      The following code example overrides the GetRequestPolicy method and specifies that the policy is named ForwardRequestPolicy and that it is defined in the SOAP router's policy file.

      Protected Overrides Function GetForwardRequestPolicy() As Policy
          Return Policies.Default("ForwardRequestPolicy")
      End Function
      
      protected override Policy GetForwardRequestPolicy()
      {
          return Policies.Default["ForwardRequestPolicy"];
      }
      
  9. Specify that the SOAP router runs for this Web application.

    1. In Solution Explorer, double-click Web.config.

    2. Include an <add> element for the <httpHandlers> section to specify the routing class.
      The following code example configures the WSE router to run for all SOAP requests received for files with an .asmx extension in this Web application.

      <configuration>
          <system.web>
              <httpHandlers>
                  <add verb="*" path="*.asmx"
                      type="RouterWithPolicy" />
              </httpHandlers>
          </system.web>
      </configuration>
      

      Note

      The type attribute of the <add> Element for <httpHandlers> section must be on one line, even though this example code contains line breaks for readability.

Example

The following code example secures SOAP messages sent between the client and the SOAP router by using a policy that is defined in code. SOAP messages that are sent from the SOAP router to the Web service are secured using a policy that is defined in a policy file.

Note

Typically, you would not define the policy partially in code and partially in a policy file. It is done in this example to demonstrate how to use both methods.

Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls

Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Messaging
Imports Microsoft.Web.Services3.Design

Imports System.Security.Cryptography.X509Certificates

Public Class RouterWithPolicy
    Inherits SoapHttpRouter
    Protected Overrides Function GetRequestPolicy() As Policy
        Return New RouterPolicy()
    End Function 'GetRequestPolicy
    Protected Overrides Function GetForwardRequestPolicy() As Policy
        Return Policies.Default("ForwardRequestPolicy")
    End Function

End Class 'RouterWithPolicy

Public Class RouterPolicy
    Inherits Policy

    Public Sub New()
        Dim assertion As New MutualCertificate11Assertion()

        assertion.ClientActor = "http://microsoft.web.services3.samples.securerouting/client"
        assertion.ServiceActor = "https://schemas.xmlsoap.org/soap/actor/next"

        assertion.ClientX509TokenProvider = New X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient")
        assertion.ServiceX509TokenProvider = New X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer")

        Me.Assertions.Add(assertion)
    End Sub 'New
End Class 'RouterPolicy
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Messaging;
using Microsoft.Web.Services3.Design;
using System.Security.Cryptography.X509Certificates;


public class RouterWithPolicy : SoapHttpRouter
{
    protected override Policy GetRequestPolicy()
    {
        return new RouterPolicy();
    }
    protected override Policy GetForwardRequestPolicy()
    {
        return Policies.Default["ForwardRequestPolicy"];
    }
}

public class RouterPolicy : Policy
{
    public RouterPolicy()
        : base()
    {
        MutualCertificate11Assertion assertion = new MutualCertificate11Assertion();

        assertion.ClientActor = "http://microsoft.web.services3.samples.securerouting/client";
        assertion.ServiceActor = "https://schemas.xmlsoap.org/soap/actor/next";

        assertion.ClientX509TokenProvider = new X509TokenProvider(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient");
        assertion.ServiceX509TokenProvider = new X509TokenProvider(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");

        this.Assertions.Add(assertion);
    }  
}

See Also

Tasks

How to: Create a Custom Policy Assertion that Secures SOAP Messages

Other Resources

Routing SOAP Messages with WSE