다음을 통해 공유


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

Create a custom policy assertion to enforce security requirements or modify SOAP messages when one of the Turnkey Security Assertions does not meet the application's needs.

There are two categories of custom policy assertions: Those that secure SOAP messages and those that do not. This topic provides the steps for creating a custom policy assertion that secures SOAP messages. The procedure creates a custom policy assertion that secures SOAP messages that are sent to and from the Web service using X509SecurityToken security tokens. For details about creating a custom policy assertion that does not secure SOAP messages, see How to: Create a Custom Policy Assertion that does not Secure SOAP Messages.

To create a custom policy assertion that secures a SOAP message exchange

  1. Open the project containing the Web service.

  2. Add a new class to the project.

    1. In Solution Explorer, right-click the project name, and then click Add New Item….
    2. Select Class and provide a name for the class.
    3. Click Add to dismiss the dialog and add the class to the project.
  3. Add references to the Microsoft.Web.Services3, System.Web.Services, System.Security, and System.Xml assemblies.

    1. In Solution Explorer, right-click the project name, and then click Add Reference.
    2. Click the .NET tab, press and hold the CTRL key, and click Microsoft.Web.Services3.dll, System.Web.Services.dll, System.Security.dll, and System.Xml.dll.
    3. Click OK to dismiss the dialog.
  4. Add the Imports statements or using directives that are shown in the following code example to the top of the file for the new class.

    Imports Microsoft.VisualBasic
    
    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.Xml
    Imports System.Security.Cryptography.X509Certificates
    
    Imports Microsoft.Web.Services3
    Imports Microsoft.Web.Services3.Design
    Imports Microsoft.Web.Services3.Security
    Imports Microsoft.Web.Services3.Security.Tokens
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Security.Cryptography.X509Certificates;
    using System.Xml;
    
    using Microsoft.Web.Services3;
    using Microsoft.Web.Services3.Design;
    using Microsoft.Web.Services3.Security;
    using Microsoft.Web.Services3.Security.Tokens;
    
  5. Create a custom input filter for the Web service.

    1. Add a class that derives from the ReceiveSecurityFilter class.
      The following code example defines a class that derives from the ReceiveSecurityFilter class.

      Class CustomSecurityServerInputFilter
          Inherits ReceiveSecurityFilter
      
      class CustomSecurityServerInputFilter : ReceiveSecurityFilter
      {
      
    2. Specify the security requirements for incoming SOAP messages to the Web service by overriding the ValidateMessageSecurity method.
      The following code example specifies that SOAP messages that are sent to the Web service must be signed and encrypted. The security tokens that are used to sign and encrypt the SOAP message are saved in the OperationState property, which can be accessed later by a Web service's custom output filter if a SOAP response is returned to the client. The security tokens are stored in a user-defined class named RequestState.

      Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
          Dim clientToken As SecurityToken = Nothing
          Dim serverToken As SecurityToken = Nothing
      
          ' Ensure incoming SOAP messages are signed and encrypted.
          Dim elem As ISecurityElement
          For Each elem In security.Elements
              If TypeOf elem Is MessageSignature Then
                  Dim sig As MessageSignature = CType(elem, MessageSignature)
                  clientToken = sig.SigningToken
              End If
      
              If TypeOf elem Is EncryptedData Then
                  Dim enc As EncryptedData = CType(elem, EncryptedData)
                  serverToken = enc.SecurityToken
              End If
          Next elem
      
          If clientToken Is Nothing OrElse serverToken Is Nothing Then
              Throw New Exception("Incoming message did not meet security requirements")
          End If
          Dim state As New RequestState(clientToken, serverToken)
      
          envelope.Context.OperationState.Set(state)
      End Sub 'ValidateMessageSecurity
      
      public override void  ValidateMessageSecurity(SoapEnvelope envelope, Security security)
      {
          SecurityToken clientToken = null;
          SecurityToken serverToken = null;
      
          // Ensure incoming SOAP messages are signed and encrypted.
          foreach (ISecurityElement elem in security.Elements)
          {
              if (elem is MessageSignature)
              {
                  MessageSignature sig = (MessageSignature)elem;
                  clientToken = sig.SigningToken;
              }
      
              if (elem is EncryptedData)
              {
                  EncryptedData enc = (EncryptedData)elem;
                  serverToken = enc.SecurityToken;
              }
          }
      
          if (clientToken == null || serverToken == null)
              throw new Exception("Incoming message did not meet security requirements");
      
          RequestState state = new RequestState(clientToken, serverToken);
      
          envelope.Context.OperationState.Set(state);
      }
      
  6. Create a custom output filter for the Web service.

    1. Add a class that derives from the SendSecurityFilter class.
      The following example defines a class that derives from the SendSecurityFilter class.

      Class CustomSecurityServerOutputFilter
          Inherits SendSecurityFilter
      
      class CustomSecurityServerOutputFilter : SendSecurityFilter
      {
      
    2. Secure SOAP responses that are sent from the Web service by overriding the SecureMessage method.
      The following code example signs and encrypts SOAP responses using the security tokens that encrypted and signed the SOAP request, respectively. The security tokens are retrieved from the OperationState property that was set by the Web service's custom input filter.

      Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security)
          Dim state As RequestState = envelope.Context.OperationState.Get(Of RequestState)()
      
          ' Sign the message with the Web service's security token.
          security.Tokens.Add(state.ServerToken)
          security.Elements.Add(New MessageSignature(state.ServerToken))
      
          ' Encrypt the message with the client's security token.
          security.Elements.Add(New EncryptedData(state.ClientToken))
      End Sub 'SecureMessage
      
      public override void SecureMessage(SoapEnvelope envelope, Security security)
      {
          RequestState state = envelope.Context.OperationState.Get<RequestState>();
      
          // Sign the message with the Web service's security token.
          security.Tokens.Add(state.ServerToken);
          security.Elements.Add(new MessageSignature(state.ServerToken));
      
          // Encrypt the message with the client's security token.
          security.Elements.Add(new EncryptedData(state.ClientToken));
      }
      
  7. Create a custom output filter for the client.

    1. Add a class that derives from the SendSecurityFilter class.
      The following code example defines a class that derives from the SendSecurityFilter class.

      Class CustomSecurityClientOutputFilter
          Inherits SendSecurityFilter
      
      class CustomSecurityClientOutputFilter : SendSecurityFilter
      {
      
    2. Secure SOAP responses that are sent from the client by overriding the SecureMessage method.
      The following code example signs and encrypts SOAP responses using the security tokens that are created in the custom filter's constructor. The security tokens that are used to sign and encrypt the SOAP message are saved in the OperationState property, which can be accessed later by a client's custom output filter to verify security requirements on SOAP responses that are returned by the Web service.

          Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
              MyBase.New(parentAssertion.ServiceActor, True)
              ' Get the client security token.
              clientToken = X509TokenProvider.CreateToken(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient")
      
              ' Get the server security token.
              serverToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer")
          End Sub 'New
      
      
      
      ...
      
      
              Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security)
              ' Sign the SOAP message with the client's security token.
              security.Tokens.Add(clientToken)
              security.Elements.Add(New MessageSignature(clientToken))
      
              ' Encrypt the SOAP message with the client's security token.
              security.Elements.Add(New EncryptedData(serverToken))
      
              ' Encrypt the client's security token with the server's security token.
              security.Elements.Add(New EncryptedData(serverToken, "#" + clientToken.Id))
      
              ' Store the client and server security tokens in the request state.
              Dim state As New RequestState(clientToken, serverToken)
      
              ' Store the request state in the proxy's operation state. 
              ' This makes these tokens accessible when SOAP responses are 
              ' verified to have sufficient security requirements.
              envelope.Context.OperationState.Set(state)
          End Sub 'SecureMessage
      
          public CustomSecurityClientOutputFilter(CustomSecurityAssertion parentAssertion)
              : base(parentAssertion.ServiceActor,true )
          {
              // Get the client security token.
              clientToken = X509TokenProvider.CreateToken(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient");
      
              // Get the server security token.
              serverToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");
          }
      
      
      
      ...
      
      
              public override void SecureMessage(SoapEnvelope envelope, Security security)
          {
              // Sign the SOAP message with the client's security token.
              security.Tokens.Add(clientToken);
              security.Elements.Add(new MessageSignature(clientToken));
      
              // Encrypt the SOAP message with the client's security token.
              security.Elements.Add(new EncryptedData(serverToken));
      
              // Encrypt the client's security token with the server's security token.
              security.Elements.Add(new EncryptedData(serverToken, "#" + clientToken.Id));
      
              // Store the client and server security tokens in the request state.
              RequestState state = new RequestState(clientToken, serverToken);
      
              // Store the request state in the proxy's operation state. 
              // This makes these tokens accessible when SOAP responses are 
              // verified to have sufficient security requirements.
              envelope.Context.OperationState.Set(state);
          }
      
  8. Create a custom input filter for the client.

    1. Add a class that derives from the ReceiveSecurityFilter class.
      The following code example defines a class that derives from the ReceiveSecurityFilter class.

      Class CustomSecurityClientInputFilter
          Inherits ReceiveSecurityFilter
      
      class CustomSecurityClientInputFilter : ReceiveSecurityFilter
      {
      
    2. Enforce the security requirements for SOAP responses from the Web service by overriding the ValidateMessageSecurity method.
      The following code example ensures that SOAP responses are signed using the security token that is used to encrypt the SOAP request and that is encrypted by the security token that signed the SOAP request. The security tokens are retrieved from the OperationState property that was set by the client's custom output filter.

      Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
          Dim state As RequestState
          Dim signed As Boolean = False
          Dim encrypted As Boolean = False
      
          ' Get the request state out of the operation state.
          state = envelope.Context.OperationState.Get(Of RequestState)()
      
          ' Make sure the message was signed with the server's security token.
          Dim elem As ISecurityElement
          For Each elem In security.Elements
              If TypeOf elem Is MessageSignature Then
                  Dim sig As MessageSignature = CType(elem, MessageSignature)
      
                  If sig.SigningToken.Equals(state.ServerToken) Then
                      signed = True
                  End If
              End If
              If TypeOf elem Is EncryptedData Then
                  Dim enc As EncryptedData = CType(elem, EncryptedData)
      
                  If enc.SecurityToken.Equals(state.ClientToken) Then
                      encrypted = True
                  End If
              End If
          Next elem
          If Not signed OrElse Not encrypted Then
              Throw New Exception("Response message does not meet security requirements")
          End If
      End Sub 'ValidateMessageSecurity
      
      public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security)
      {
          RequestState state;
          bool signed = false;
          bool encrypted = false;
      
          // Get the request state out of the operation state.
          state = envelope.Context.OperationState.Get<RequestState>();
      
          // Make sure the message was signed with the server's security token.
          foreach (ISecurityElement elem in security.Elements)
          {
              if (elem is MessageSignature)
              {
                  MessageSignature sig = (MessageSignature)elem;
      
                  if (sig.SigningToken.Equals(state.ServerToken))
                      signed = true;
              }
      
              if (elem is EncryptedData)
              {
                  EncryptedData enc = (EncryptedData)elem;
      
                  if (enc.SecurityToken.Equals(state.ClientToken))
                      encrypted = true;
              }
          }
      
          if (!signed || !encrypted)
              throw new Exception("Response message does not meet security requirements");
      }
      
  9. Create a class that represents the custom policy assertion.

    1. Create a class that derives from the SecurityPolicyAssertion class.
      The following code example defines a class that derives from the SecurityPolicyAssertion class.

      Class CustomSecurityAssertion
          Inherits SecurityPolicyAssertion
      
      class CustomSecurityAssertion : SecurityPolicyAssertion
      {
      
    2. Specify the Web service's custom input filter by overriding the CreateServiceInputFilter method.
      When a custom policy assertion does not enforce security on SOAP requests that are sent to the Web service, set the return value of the CreateServiceInputFilter method to a null reference (Nothing in Visual Basic).
      The following code example adds a custom input filter for the Web service.

      Public Overrides Function CreateServiceInputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return New CustomSecurityServerInputFilter(Me)
      End Function 'CreateServiceInputFilter
      
      public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
      {
          return new CustomSecurityServerInputFilter(this);
      }
      
    3. Specify the Web service's custom output filter by overriding the CreateServiceOutputFilter method.
      When a custom policy assertion does not enforce security on SOAP responses that are sent by the Web service, set the return value of the CreateServiceOutputFilter method to a null reference (Nothing in Visual Basic).
      The following code example adds a custom output filter for the Web service.

      Public Overrides Function CreateServiceOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return New CustomSecurityServerOutputFilter(Me)
      End Function 'CreateServiceOutputFilter
      
      public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
      {
          return new CustomSecurityServerOutputFilter(this);
      }
      
    4. Specify the client's custom input filter by overriding the CreateClientInputFilter method.
      When a custom policy assertion does not enforce security on SOAP responses that are received by the client, set the return value of the CreateClientInputFilter method to a null reference (Nothing in Visual Basic)
      The following code example adds a custom input filter for the client.

      Public Overrides Function CreateClientInputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return Nothing
      End Function 'CreateClientInputFilter
      
      public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
      {
          return new CustomSecurityClientInputFilter(this);
      }
      
    5. Specify the client's custom output filter by overriding the CreateClientOutputFilter method.
      When a custom policy assertion does not enforce security on SOAP requests that are sent by the client, set the return value of the CreateClientOutputFilter method to a null reference (Nothing in Visual Basic).
      The following code example adds a custom output filter for the client.

      Public Overrides Function CreateClientOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
          Return Nothing
      End Function 'CreateClientOutputFilter
      
      public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
      {
          return new CustomSecurityClientOutputFilter(this);
      }
      
    6. Add code to parse the custom XML elements and attributes that can be placed in a policy file for this custom policy assertion by overriding the ReadXml and GetExtensions methods.
      Like the turnkey security assertions, custom policy assertions can optionally provide an XML element that is used to specify the custom policy assertion's options in a policy file. The XML element can contain child elements and attributes that specify the options for the custom policy assertion.
      A System.Xml.XmlReader is passed into the ReadXml method with the reader positioned on the XML element for the custom policy assertion. The name of the XML element is specified when the custom policy assertion is registered in the policy file using an <extension> Element. Use the System.Xml.XmlReader to retrieve the custom policy assertion's options that are set in the policy file.
      Override the GetExtensions method to associate the name of the XML element that is used to represent the policy assertion in a policy file with the type that implements the policy assertion.
      Typically, it is best to provide support for reading an XML element from a policy file for the custom policy assertion, so that policy for the application can be configured at deployment time to match the application's environment.
      The following code example verifies that the current element is named CustomSecurityAssertion and then reads it. To see an example policy file with the custom policy assertion, see How to: Secure an Application Using a Custom Policy Assertion.

              Public Overrides Sub ReadXml(ByVal reader As XmlReader, ByVal extensions As IDictionary(Of String, Type))
                  If reader Is Nothing Then
                      Throw New ArgumentNullException("reader")
                  End If
                  If extensions Is Nothing Then
                      Throw New ArgumentNullException("extensions")
                  End If
                  Dim isEmpty As Boolean = reader.IsEmptyElement
                  MyBase.ReadAttributes(reader)
                  reader.ReadStartElement("CustomSecurityAssertion")
      
                  If Not isEmpty Then
                      ' Read the contents of the <clientToken> element.
                      If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "clientToken" Then
                          reader.ReadStartElement()
                          reader.MoveToContent()
      
                          ' Get the registed security token provider for X.509 certificate security credentials. 
                          Dim type As Type = extensions(reader.Name)
                          Dim instance As Object = Activator.CreateInstance(type)
      
                          If instance Is Nothing Then
                              Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type 0End.", type.AssemblyQualifiedName))
                          End If
                          Dim clientProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))
      
                          ' Read the child elements that provide the details about the client's X.509 certificate. 
                          clientProvider.ReadXml(reader, extensions)
                          Me.ClientX509TokenProvider = clientProvider
                          reader.ReadEndElement()
                      End If
                      ' Read the contents of the <serviceToken> element.
                      If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "serviceToken" Then
                          reader.ReadStartElement()
                          reader.MoveToContent()
      
                          ' Get the registed security token provider for X.509 certificate security credentials. 
                          Dim type As Type = extensions(reader.Name)
                          Dim instance As Object = Activator.CreateInstance(type)
      
                          If instance Is Nothing Then
                              Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type 0End.", type.AssemblyQualifiedName))
                          End If
                          Dim serviceProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))
      
                          ' Read the child elements that provide the details about the client's X.509 certificate. 
                          serviceProvider.ReadXml(reader, extensions)
                          Me.ServiceX509TokenProvider = serviceProvider
                          reader.ReadEndElement()
                      End If
                      MyBase.ReadElements(reader, extensions)
                      reader.ReadEndElement()
                  End If
              End Sub
      
      
      
          ...
      
      
                  public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
              {
                  // Add the CustomSecurityAssertion custom policy assertion to the list of registered
                  // policy extensions.
                  List<KeyValuePair<string, Type>> extensions = new List<KeyValuePair<string, Type>>();
                  extensions.Add(new KeyValuePair<string, Type>("CustomSecurityAssertion", this.GetType()));
                  if (serviceX509TokenProviderValue != null)
                  {
                      // Add any policy extensions that read child elements of the <serviceToken> element
                      // to the list of registered policy extensions.
                      IEnumerable<KeyValuePair<string, Type>> innerExtensions = serviceX509TokenProviderValue.GetExtensions();
                      if (innerExtensions != null)
                      {
                          foreach (KeyValuePair<string, Type> extension in innerExtensions)
                          {
                              extensions.Add(extension);
                          }
                      }
                  }
                  if (clientX509TokenProviderValue != null)
                  {
                      // Add any policy extensions that read child elements of the <clientToken> element
                      // to the list of registered policy extensions.
                      IEnumerable<KeyValuePair<string, Type>> innerExtensions = clientX509TokenProviderValue.GetExtensions();
                      if (innerExtensions != null)
                      {
                          foreach (KeyValuePair<string, Type> extension in innerExtensions)
                          {
                              extensions.Add(extension);
                          }
                      }
                  }
                  return extensions;
              }
              // </snippet16
      
          }
      
          class RequestState
          {
              SecurityToken clientToken;
              SecurityToken serverToken;
      
              public RequestState(SecurityToken cToken, SecurityToken sToken)
              {
                  clientToken = cToken;
                  serverToken = sToken;
              }
      
              public SecurityToken ClientToken
              {
                  get { return clientToken; }
              }
      
              public SecurityToken ServerToken
              {
                  get { return serverToken; }
              }
          }
          class CustomSecurityServerInputFilter : ReceiveSecurityFilter
          {
              public CustomSecurityServerInputFilter(CustomSecurityAssertion parentAssertion)
                  : base(parentAssertion.ServiceActor, false)
              {
      
              }
              public override void  ValidateMessageSecurity(SoapEnvelope envelope, Security security)
              {
                  SecurityToken clientToken = null;
                  SecurityToken serverToken = null;
      
                  // Ensure incoming SOAP messages are signed and encrypted.
                  foreach (ISecurityElement elem in security.Elements)
                  {
                      if (elem is MessageSignature)
                      {
                          MessageSignature sig = (MessageSignature)elem;
                          clientToken = sig.SigningToken;
                      }
      
                      if (elem is EncryptedData)
                      {
                          EncryptedData enc = (EncryptedData)elem;
                          serverToken = enc.SecurityToken;
                      }
                  }
      
                  if (clientToken == null || serverToken == null)
                      throw new Exception("Incoming message did not meet security requirements");
      
                  RequestState state = new RequestState(clientToken, serverToken);
      
                  envelope.Context.OperationState.Set(state);
              }
          }
      
          class CustomSecurityServerOutputFilter : SendSecurityFilter
          {
      
              public CustomSecurityServerOutputFilter(CustomSecurityAssertion parentAssertion)
                  : base(parentAssertion.ServiceActor,false )
              {
              }
      
              public override void SecureMessage(SoapEnvelope envelope, Security security)
              {
                  RequestState state = envelope.Context.OperationState.Get<RequestState>();
      
                  // Sign the message with the Web service's security token.
                  security.Tokens.Add(state.ServerToken);
                  security.Elements.Add(new MessageSignature(state.ServerToken));
      
                  // Encrypt the message with the client's security token.
                  security.Elements.Add(new EncryptedData(state.ClientToken));
              }
          }
          class CustomSecurityClientInputFilter : ReceiveSecurityFilter
          {
              public CustomSecurityClientInputFilter(CustomSecurityAssertion parentAssertion)
                  : base(parentAssertion.ServiceActor,true )
              {
      
              }
      
              public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security)
              {
                  RequestState state;
                  bool signed = false;
                  bool encrypted = false;
      
                  // Get the request state out of the operation state.
                  state = envelope.Context.OperationState.Get<RequestState>();
      
                  // Make sure the message was signed with the server's security token.
                  foreach (ISecurityElement elem in security.Elements)
                  {
                      if (elem is MessageSignature)
                      {
                          MessageSignature sig = (MessageSignature)elem;
      
                          if (sig.SigningToken.Equals(state.ServerToken))
                              signed = true;
                      }
      
                      if (elem is EncryptedData)
                      {
                          EncryptedData enc = (EncryptedData)elem;
      
                          if (enc.SecurityToken.Equals(state.ClientToken))
                              encrypted = true;
                      }
                  }
      
                  if (!signed || !encrypted)
                      throw new Exception("Response message does not meet security requirements");
              }
          }
          class CustomSecurityClientOutputFilter : SendSecurityFilter
          {
              SecurityToken clientToken;
              SecurityToken serverToken;
      
              public CustomSecurityClientOutputFilter(CustomSecurityAssertion parentAssertion)
                  : base(parentAssertion.ServiceActor,true )
              {
                  // Get the client security token.
                  clientToken = X509TokenProvider.CreateToken(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient");
      
                  // Get the server security token.
                  serverToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");
              }
      
              public override void SecureMessage(SoapEnvelope envelope, Security security)
              {
                  // Sign the SOAP message with the client's security token.
                  security.Tokens.Add(clientToken);
                  security.Elements.Add(new MessageSignature(clientToken));
      
                  // Encrypt the SOAP message with the client's security token.
                  security.Elements.Add(new EncryptedData(serverToken));
      
                  // Encrypt the client's security token with the server's security token.
                  security.Elements.Add(new EncryptedData(serverToken, "#" + clientToken.Id));
      
                  // Store the client and server security tokens in the request state.
                  RequestState state = new RequestState(clientToken, serverToken);
      
                  // Store the request state in the proxy's operation state. 
                  // This makes these tokens accessible when SOAP responses are 
                  // verified to have sufficient security requirements.
                  envelope.Context.OperationState.Set(state);
              }
          }
      }
      using System;
      using System.IO;
      using System.Xml;
      using System.Collections.Generic;
      using System.Text;
      using System.Security.Cryptography.X509Certificates;
      
      using Microsoft.Web.Services3;
      using Microsoft.Web.Services3.Design;
      using Microsoft.Web.Services3.Security;
      using Microsoft.Web.Services3.Security.Tokens;
      
      namespace CustomPolicyAssertions
      {
          class CustomTraceAssertion : PolicyAssertion
          {
              string inputfile = "input.xml";
              string outputfile = "output.xml";
      
              public CustomTraceAssertion()
                  : base()
              {
              }
      
              public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
              {
                  return new CustomTraceFilter(outputfile);
              }
      
              public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
              {
                  return new CustomTraceFilter(inputfile);
              }
      
              public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
              {
                  return new CustomTraceFilter(inputfile);
              }
      
              public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
              {
                  return new CustomTraceFilter(outputfile);
              }
      
              public override void ReadXml(XmlReader reader, IDictionary<string, Type> extensions)
              {
                  bool isEmpty = reader.IsEmptyElement;
      
                  string input = reader.GetAttribute("input");
                  string output = reader.GetAttribute("output");
      
                  if (input != null)
                      inputfile = input;
      
                  if (output != null)
                      outputfile = output;
      
                  reader.ReadStartElement("CustomTraceAssertion");
                  if (!isEmpty)
                      reader.ReadEndElement();
              }
      
              public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
              {
                  return new KeyValuePair<string, Type>[] { new KeyValuePair<string, Type>("CustomTraceAssertion", this.GetType()) };
              }
          }
      
          class CustomTraceFilter : SoapFilter
          {
              string filename = null;
              public CustomTraceFilter(string file)
                  : base()
              {
                  filename = file;
              }
      
              public override SoapFilterResult ProcessMessage(SoapEnvelope envelope)
              {
                  XmlDocument dom = null;
                  DateTime timeStamp = DateTime.Now;
                  XmlNode rootNode = null;
      
                  dom = new XmlDocument();
      
                  if (!File.Exists(filename))
                  {
                      XmlDeclaration xmlDecl = dom.CreateXmlDeclaration("1.0", "utf-8", null);
      
                      dom.InsertBefore(xmlDecl, dom.DocumentElement);
      
                      rootNode = dom.CreateNode(XmlNodeType.Element, "log", String.Empty);
                      dom.AppendChild(rootNode);
                      dom.Save(filename);
                  }
                  else
                  {
                      dom.Load(filename);
                      rootNode = dom.DocumentElement;
                  }
      
      
                  XmlNode newNode = dom.ImportNode(envelope.DocumentElement, true);
                  rootNode.AppendChild(newNode);
      
                  dom.Save(filename );
      
                  return SoapFilterResult.Continue;
              }
          }
      
      
      }
      fxcopcmd.exe /p:"C:\Security.FxCop" /plat:"C:\WINNT\Microsoft.NET\Framework\v2.0.50215" /c /d:"C:\Program Files\Microsoft WSE\v3.0" /f:"c:\samples\wse\wseCustomPolicyAssertion\cs\bin\Debug\Client.exe" /f:"c:\samples\wse\wseCustomPolicyAssertion\cs\bin\Debug\Client.vshost.exe" /f:"c:\samples\wse\wseCustomPolicyAssertion\cs\obj\Debug\Client.exe"
      Microsoft FxCopCmd v1.312
      Copyright (C) 1999-2004 Microsoft Corp.  All rights reserved.
      
      Loading C:\Security.FxCop...
      Loaded SecurityRules.dll...
      Found project override for platform assemblies location.
      Using system files at: C:\WINNT\Microsoft.NET\Framework\v2.0.50215.
      4 exceptions occurred while loading mscorlib.
         0) Attempted to read or write protected memory. This is often an indication that other memory has been corrupted.
         1) Bad serialized type name
      Could not resolve reference to System.Configuration.
      5 exceptions occurred while loading Client.
         0) Bad serialized type name
         1) Assembly reference not resolved: System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
      Loaded Client.exe...
      1 exceptions occurred while loading vshost.
         0) Bad serialized type name
      Loaded Client.vshost.exe...
      4 exceptions occurred while loading Client.
         0) Bad serialized type name
      Loaded Client.exe...
      Initializing Introspection engine...
      Could not resolve reference to Microsoft.VisualStudio.HostingProcess.Utilities.Sync.
      Could not resolve reference to Microsoft.VisualStudio.HostingProcess.Utilities.Sync.
      5 exceptions occurred while loading vshost.
         0) Could not resolve member reference: Microsoft.VisualStudio.HostingProcess.Synchronize::get_HostingProcessInitialized
         1) Assembly reference not resolved: Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
         2) Could not resolve member reference: Microsoft.VisualStudio.HostingProcess.Synchronize::get_StartRunningUsersAssembly
         3) Bad serialized type name
         4) Could not resolve type reference: [Microsoft.VisualStudio.HostingProcess.Utilities.Sync]Microsoft.VisualStudio.HostingProcess.Synchronize
      12 exceptions occurred while loading Client.
         00) Could not resolve member reference: System.Configuration.ConfigurationManager::get_AppSettings
         01) Could not resolve type reference: [System.Configuration]System.Configuration.ConfigurationManager
         02) Could not resolve type reference: [System]System.Security.Cryptography.X509Certificates.StoreLocation
         03) Could not resolve type reference: [mscorlib]System.Collections.ObjectModel.Collection`1
         04) Could not resolve member reference: System.Web.Services.Protocols.WebClientProtocol::get_UseDefaultCredentials
         05) Bad serialized type name
         06) Could not resolve member reference: Microsoft.Web.Services3.Design.Policy::get_Assertions
         07) Could not resolve member reference: System.Web.Services.Protocols.WebClientProtocol::set_UseDefaultCredentials
         08) Could not resolve member reference: System.Collections.ObjectModel.Collection`1::Add
         09) Could not resolve member reference: Microsoft.Web.Services3.Design.X509TokenProvider::CreateToken
         10) Could not resolve type reference: [System]System.Security.Cryptography.X509Certificates.StoreName
         11) Bad type parameter in position 0 for type=Client.ClientPolicy
      8 exceptions occurred while loading Client.
         0) Could not resolve type reference: [System]System.Security.Cryptography.X509Certificates.StoreLocation
         1) Could not resolve type reference: [mscorlib]System.Collections.ObjectModel.Collection`1
         2) Bad serialized type name
         3) Could not resolve member reference: Microsoft.Web.Services3.Design.Policy::get_Assertions
         4) Could not resolve member reference: System.Collections.ObjectModel.Collection`1::Add
         5) Could not resolve member reference: Microsoft.Web.Services3.Design.X509TokenProvider::CreateToken
         6) Could not resolve type reference: [System]System.Security.Cryptography.X509Certificates.StoreName
         7) Bad type parameter in position 0 for type=Client.ClientPolicy
      Analyzing...
      Analysis Complete.
      No messages written.
      Done.
      
      WARNING: the following missing references were detected.
      Analysis might be compromised. Use the '/directory' switch.
      to specify additional assembly reference search paths.
      
      * System.Configuration Version=2.0.0.0, used by:Client
      * Microsoft.VisualStudio.HostingProcess.Utilities.Sync Version=8.0.0.0, used by:vshost
      
      
      
      
      using System;
      using System.Collections.Generic;
      using System.Text;
      
      using Microsoft.Web.Services3;
      using Microsoft.Web.Services3.Security;
      using Microsoft.Web.Services3.Design;
      
      using Client.localhost;
      using CustomPolicyAssertions;
      
      namespace Client
      {
          class Program
          {
              static void Main(string[] args)
              {
                  ServiceWse serviceProxy = new ServiceWse();
      
                  serviceProxy.SetPolicy("ClientPolicy");
      
                  Console.WriteLine("Web service returned: {0}", serviceProxy.HelloWorld());
              }
          }
      
          class ClientPolicy : Policy
          {
              public ClientPolicy()
                  : base()
              {
                  this.Assertions.Add(new CustomSecurityAssertion());
                  this.Assertions.Add(new CustomTraceAssertion());
              }
          }
      }
      <policies>
        <extensions>
          <extension name="CustomSecurityAssertion" type="CustomPolicyAssertions.CustomSecurityAssertion, Client" />
          <extension name="CustomTraceAssertion" type="CustomPolicyAssertions.CustomTraceAssertion, Client" />
        </extensions>
        <policy name="ClientPolicy">
            <CustomTraceAssertion input="input-before.xml" output="output-before.xml"/>
            <CustomSecurityAssertion />
            <CustomTraceAssertion input="input-after.xml" output="output-after.xml"/>
        </policy>
      </policies>
      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <configSections>
          <section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="ClientVB.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" />
          </sectionGroup>
          <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="ClientVB.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          </sectionGroup>
        </configSections>
        <microsoft.web.services3>
          <tokenIssuer>
              <statefulSecurityContextToken enabled="true" />
          </tokenIssuer>
          <diagnostics>
              <trace enabled="true" input="InputTrace.webinfo" output="OutputTrace.webinfo" />
          </diagnostics>
          <security>
              <x509 storeLocation="CurrentUser" allowTestRoot="true" />
          </security>
          <policy fileName="..\..\wse3policyCache.config" />
      </microsoft.web.services3>
        <userSettings>
          <ClientVB.Settings />
        </userSettings>
        <applicationSettings>
          <ClientVB.Settings>
            <setting name="ClientVB_localhost_Service" serializeAs="String">
              <value>https://localhost/CustomPolicyServiceVB/Service.asmx</value>
            </setting>
          </ClientVB.Settings>
        </applicationSettings>
      </configuration>
      
      Microsoft Visual Studio Solution File, Format Version 9.00
      # Visual Studio 2005
      Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ClientVB", "ClientVB.vbproj", "{02C3A5FE-44CE-4457-BCF5-D0936247EC15}"
      EndProject
      Global
          GlobalSection(SolutionConfigurationPlatforms) = preSolution
              Debug|Any CPU = Debug|Any CPU
              Release|Any CPU = Release|Any CPU
          EndGlobalSection
          GlobalSection(ProjectConfigurationPlatforms) = postSolution
              {02C3A5FE-44CE-4457-BCF5-D0936247EC15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
              {02C3A5FE-44CE-4457-BCF5-D0936247EC15}.Debug|Any CPU.Build.0 = Debug|Any CPU
              {02C3A5FE-44CE-4457-BCF5-D0936247EC15}.Release|Any CPU.ActiveCfg = Release|Any CPU
              {02C3A5FE-44CE-4457-BCF5-D0936247EC15}.Release|Any CPU.Build.0 = Release|Any CPU
          EndGlobalSection
          GlobalSection(SolutionProperties) = preSolution
              HideSolutionNode = FALSE
          EndGlobalSection
      EndGlobal
      <?xml version="1.0" encoding="utf-8"?>
      <Project DefaultTargets="Build" xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
        <PropertyGroup>
          <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
          <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
          <ProductVersion>8.0.50215</ProductVersion>
          <SchemaVersion>2.0</SchemaVersion>
          <ProjectGuid>{02C3A5FE-44CE-4457-BCF5-D0936247EC15}</ProjectGuid>
          <OutputType>Exe</OutputType>
          <StartupObject>ClientVB.Program</StartupObject>
          <RootNamespace>ClientVB</RootNamespace>
          <AssemblyName>ClientVB</AssemblyName>
          <MyType>Console</MyType>
        </PropertyGroup>
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
          <DebugSymbols>true</DebugSymbols>
          <DebugType>full</DebugType>
          <DefineDebug>true</DefineDebug>
          <DefineTrace>true</DefineTrace>
          <OutputPath>bin\Debug\</OutputPath>
          <DocumentationFile>ClientVB.xml</DocumentationFile>
          <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
        </PropertyGroup>
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
          <DebugType>pdbonly</DebugType>
          <DefineDebug>false</DefineDebug>
          <DefineTrace>true</DefineTrace>
          <Optimize>true</Optimize>
          <OutputPath>bin\Release\</OutputPath>
          <DocumentationFile>ClientVB.xml</DocumentationFile>
          <NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
        </PropertyGroup>
        <ItemGroup>
          <Reference Include="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
          <Reference Include="System" />
          <Reference Include="System.Configuration" />
          <Reference Include="System.Data" />
          <Reference Include="System.Deployment" />
          <Reference Include="System.EnterpriseServices" />
          <Reference Include="System.Security" />
          <Reference Include="System.Web.Services" />
          <Reference Include="System.Xml" />
        </ItemGroup>
        <ItemGroup>
          <Import Include="Microsoft.VisualBasic" />
          <Import Include="System" />
          <Import Include="System.Collections" />
          <Import Include="System.Collections.Generic" />
          <Import Include="System.Console" />
          <Import Include="System.Data" />
          <Import Include="System.Diagnostics" />
        </ItemGroup>
        <ItemGroup>
          <Compile Include="CustomSecurityAssertion.vb" />
          <Compile Include="CustomTraceAssertion.vb" />
          <Compile Include="Program.vb" />
          <Compile Include="My Project\AssemblyInfo.vb" />
          <Compile Include="My Project\Application.Designer.vb">
            <AutoGen>True</AutoGen>
            <DependentUpon>Application.myapp</DependentUpon>
          </Compile>
          <Compile Include="My Project\Resources.Designer.vb">
            <AutoGen>True</AutoGen>
            <DesignTime>True</DesignTime>
            <DependentUpon>Resources.resx</DependentUpon>
          </Compile>
          <Compile Include="My Project\Settings.Designer.vb">
            <AutoGen>True</AutoGen>
            <DependentUpon>Settings.settings</DependentUpon>
            <DesignTimeSharedInput>True</DesignTimeSharedInput>
          </Compile>
          <Compile Include="Web References\localhost\Reference.vb">
            <AutoGen>True</AutoGen>
            <DesignTime>True</DesignTime>
            <DependentUpon>Reference.map</DependentUpon>
          </Compile>
        </ItemGroup>
        <ItemGroup>
          <EmbeddedResource Include="My Project\Resources.resx">
            <Generator>VbMyResourcesResXFileCodeGenerator</Generator>
            <LastGenOutput>Resources.Designer.vb</LastGenOutput>
            <CustomToolNamespace>My.Resources</CustomToolNamespace>
          </EmbeddedResource>
        </ItemGroup>
        <ItemGroup>
          <None Include="app.config" />
          <None Include="My Project\Application.myapp">
            <Generator>MyApplicationCodeGenerator</Generator>
            <LastGenOutput>Application.Designer.vb</LastGenOutput>
          </None>
          <None Include="My Project\Settings.settings">
            <Generator>SettingsSingleFileGenerator</Generator>
            <LastGenOutput>Settings.Designer.vb</LastGenOutput>
          </None>
        </ItemGroup>
        <ItemGroup>
          <WebReferences Include="Web References\" />
        </ItemGroup>
        <ItemGroup>
          <WebReferenceUrl Include="https://localhost/CustomPolicyServiceVB/Service.asmx">
            <UrlBehavior>Dynamic</UrlBehavior>
            <RelPath>Web References\localhost\</RelPath>
            <UpdateFromURL>https://localhost/CustomPolicyServiceVB/Service.asmx</UpdateFromURL>
            <ServiceLocationURL>
            </ServiceLocationURL>
            <CachedDynamicPropName>
            </CachedDynamicPropName>
            <CachedAppSettingsObjectName>Settings</CachedAppSettingsObjectName>
            <CachedSettingsPropName>ClientVB_localhost_Service</CachedSettingsPropName>
          </WebReferenceUrl>
        </ItemGroup>
        <ItemGroup>
          <None Include="Web References\localhost\Reference.map">
            <Generator>MSDiscoCodeGenerator</Generator>
            <LastGenOutput>Reference.vb</LastGenOutput>
          </None>
          <None Include="Web References\localhost\Service.disco" />
          <None Include="Web References\localhost\Service.wsdl" />
          <None Include="wse3policyCache.config" />
        </ItemGroup>
        <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
      </Project>
      <Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
        <PropertyGroup>
          <LastOpenVersion>8.0.50215</LastOpenVersion>
          <ProjectView>ProjectFiles</ProjectView>
        </PropertyGroup>
      </Project>
      Imports Microsoft.VisualBasic
      
      Imports System
      Imports System.Collections.Generic
      Imports System.Text
      Imports System.Xml
      Imports System.Security.Cryptography.X509Certificates
      
      Imports Microsoft.Web.Services3
      Imports Microsoft.Web.Services3.Design
      Imports Microsoft.Web.Services3.Security
      Imports Microsoft.Web.Services3.Security.Tokens
      Namespace CustomPolicyAssertions
      
          Class CustomSecurityAssertion
              Inherits SecurityPolicyAssertion
              Dim serviceX509TokenProviderValue As TokenProvider(Of X509SecurityToken)
              Dim clientX509TokenProviderValue As TokenProvider(Of X509SecurityToken)
      
              Public Property ClientX509TokenProvider() As TokenProvider(Of X509SecurityToken)
      
                  Get
      
                      Return clientX509TokenProviderValue
                  End Get
                  Set(ByVal value As TokenProvider(Of X509SecurityToken))
      
                      clientX509TokenProviderValue = value
                  End Set
              End Property
      
              Public Property ServiceX509TokenProvider() As TokenProvider(Of X509SecurityToken)
      
                  Get
      
                      Return serviceX509TokenProviderValue
                  End Get
                  Set(ByVal value As TokenProvider(Of X509SecurityToken))
      
                      serviceX509TokenProviderValue = value
                  End Set
              End Property
      
              Public Sub New()
              End Sub 'New
      
              Public Overrides Function CreateClientOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
                  Return Nothing
              End Function 'CreateClientOutputFilter
      
              Public Overrides Function CreateClientInputFilter(ByVal context As FilterCreationContext) As SoapFilter
                  Return Nothing
              End Function 'CreateClientInputFilter
      
              Public Overrides Function CreateServiceInputFilter(ByVal context As FilterCreationContext) As SoapFilter
                  Return New CustomSecurityServerInputFilter(Me)
              End Function 'CreateServiceInputFilter
      
              Public Overrides Function CreateServiceOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
                  Return New CustomSecurityServerOutputFilter(Me)
              End Function 'CreateServiceOutputFilter
      
              Public Overrides Sub ReadXml(ByVal reader As XmlReader, ByVal extensions As IDictionary(Of String, Type))
                  If reader Is Nothing Then
                      Throw New ArgumentNullException("reader")
                  End If
                  If extensions Is Nothing Then
                      Throw New ArgumentNullException("extensions")
                  End If
                  Dim isEmpty As Boolean = reader.IsEmptyElement
                  MyBase.ReadAttributes(reader)
                  reader.ReadStartElement("CustomSecurityAssertion")
      
                  If Not isEmpty Then
                      ' Read the contents of the <clientToken> element.
                      If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "clientToken" Then
                          reader.ReadStartElement()
                          reader.MoveToContent()
      
                          ' Get the registed security token provider for X.509 certificate security credentials. 
                          Dim type As Type = extensions(reader.Name)
                          Dim instance As Object = Activator.CreateInstance(type)
      
                          If instance Is Nothing Then
                              Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type 0End.", type.AssemblyQualifiedName))
                          End If
                          Dim clientProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))
      
                          ' Read the child elements that provide the details about the client's X.509 certificate. 
                          clientProvider.ReadXml(reader, extensions)
                          Me.ClientX509TokenProvider = clientProvider
                          reader.ReadEndElement()
                      End If
                      ' Read the contents of the <serviceToken> element.
                      If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "serviceToken" Then
                          reader.ReadStartElement()
                          reader.MoveToContent()
      
                          ' Get the registed security token provider for X.509 certificate security credentials. 
                          Dim type As Type = extensions(reader.Name)
                          Dim instance As Object = Activator.CreateInstance(type)
      
                          If instance Is Nothing Then
                              Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type 0End.", type.AssemblyQualifiedName))
                          End If
                          Dim serviceProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))
      
                          ' Read the child elements that provide the details about the client's X.509 certificate. 
                          serviceProvider.ReadXml(reader, extensions)
                          Me.ServiceX509TokenProvider = serviceProvider
                          reader.ReadEndElement()
                      End If
                      MyBase.ReadElements(reader, extensions)
                      reader.ReadEndElement()
                  End If
              End Sub
              Public Overrides Function GetExtensions() As IEnumerable(Of KeyValuePair(Of String, Type))
              Public Overrides Function GetExtensions() As IEnumerable(Of KeyValuePair(Of String, Type))
      
      
                  ' Add the CustomSecurityAssertion custom policy assertion to the list of registered
                  ' Add the CustomSecurityAssertion custom policy assertion to the list of registered
                  ' policy extensions.
                  ' policy extensions.
                  Dim extensions As New List(Of KeyValuePair(Of String, Type))
                  Dim extensions As New List(Of KeyValuePair(Of String, Type))
                  extensions.Add(New KeyValuePair(Of String, Type)("CustomSecurityAssertion", Me.GetType()))
                  extensions.Add(New KeyValuePair(Of String, Type)("CustomSecurityAssertion", Me.GetType()))
                  If (Not serviceX509TokenProviderValue Is Nothing) Then
                  If (Not serviceX509TokenProviderValue Is Nothing) Then
      
      
                      ' Add any policy extensions that read child elements of the <serviceToken> element
                      ' Add any policy extensions that read child elements of the <serviceToken> element
                      ' to the list of registered policy extensions.
                      ' to the list of registered policy extensions.
                      Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = serviceX509TokenProviderValue.GetExtensions()
                      Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = serviceX509TokenProviderValue.GetExtensions()
                      If (Not innerExtensions Is Nothing) Then
                      If (Not innerExtensions Is Nothing) Then
                          Dim extension As KeyValuePair(Of String, Type)
                          Dim extension As KeyValuePair(Of String, Type)
                          For Each extension In innerExtensions
                          For Each extension In innerExtensions
                              extensions.Add(extension)
                              extensions.Add(extension)
                          Next
                          Next
                      End If
                      End If
                  End If
                  End If
                  If (Not clientX509TokenProviderValue Is Nothing) Then
                  If (Not clientX509TokenProviderValue Is Nothing) Then
      
      
                      ' Add any policy extensions that read child elements of the <clientToken> element
                      ' Add any policy extensions that read child elements of the <clientToken> element
                      ' to the list of registered policy extensions.
                      ' to the list of registered policy extensions.
                      Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = clientX509TokenProviderValue.GetExtensions()
                      Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = clientX509TokenProviderValue.GetExtensions()
                      If (Not innerExtensions Is Nothing) Then
                      If (Not innerExtensions Is Nothing) Then
                          Dim extension As KeyValuePair(Of String, Type)
                          Dim extension As KeyValuePair(Of String, Type)
                          For Each extension In innerExtensions
                          For Each extension In innerExtensions
                              extensions.Add(extension)
                              extensions.Add(extension)
                          Next
                          Next
                      End If
                      End If
                  End If
                  End If
                  Return extensions
                  Return extensions
              End Function
              End Function
      
      public override void ReadXml(System.Xml.XmlReader reader, IDictionary<string, Type> extensions)
      {
          if (reader == null)
              throw new ArgumentNullException("reader");
          if (extensions == null)
              throw new ArgumentNullException("extensions");
      
          bool isEmpty = reader.IsEmptyElement;
          base.ReadAttributes(reader);
          reader.ReadStartElement("CustomSecurityAssertion");
      
          if (!isEmpty)
          {
              if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "clientToken")
              {
                  reader.ReadStartElement();
                  reader.MoveToContent();
                  // Get the registed security token provider for X.509 certificate security credentials. 
                  Type type = extensions[reader.Name];
                  object instance = Activator.CreateInstance(type);
      
                  if (instance == null)
                      throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));
      
                  TokenProvider<X509SecurityToken> clientProvider = instance as TokenProvider<X509SecurityToken>;
      
                  // Read the child elements that provide the details about the client's X.509 certificate. 
                  clientProvider.ReadXml(reader, extensions);
                  this.ClientX509TokenProvider = clientProvider;
                  reader.ReadEndElement();
              }
              if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "serviceToken")
              {
                  reader.ReadStartElement();
                  reader.MoveToContent();
      
                  // Get the registed security token provider for X.509 certificate security credentials. 
                  Type type = extensions[reader.Name];
                  object instance = Activator.CreateInstance(type);
      
                  if (instance == null)
                      throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));
      
                  TokenProvider<X509SecurityToken> serviceProvider = instance as TokenProvider<X509SecurityToken>;
                  // Read the child elements that provide the details about the Web service's X.509 certificate.
                  serviceProvider.ReadXml(reader, extensions);
                  this.ServiceX509TokenProvider = serviceProvider;
                  reader.ReadEndElement();
              }
              base.ReadElements(reader, extensions);
              reader.ReadEndElement();
          }
      }
      

Example

The following code example is a custom policy assertion that signs and encrypts SOAP messages that are sent to and from the Web service using X509SecurityToken security tokens.

Imports Microsoft.VisualBasic

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Security.Cryptography.X509Certificates

Imports Microsoft.Web.Services3
Imports Microsoft.Web.Services3.Design
Imports Microsoft.Web.Services3.Security
Imports Microsoft.Web.Services3.Security.Tokens
Namespace CustomPolicyAssertions

    Class CustomSecurityAssertion
        Inherits SecurityPolicyAssertion
        Dim serviceX509TokenProviderValue As TokenProvider(Of X509SecurityToken)
        Dim clientX509TokenProviderValue As TokenProvider(Of X509SecurityToken)

        Public Property ClientX509TokenProvider() As TokenProvider(Of X509SecurityToken)

            Get

                Return clientX509TokenProviderValue
            End Get
            Set(ByVal value As TokenProvider(Of X509SecurityToken))

                clientX509TokenProviderValue = value
            End Set
        End Property

        Public Property ServiceX509TokenProvider() As TokenProvider(Of X509SecurityToken)

            Get

                Return serviceX509TokenProviderValue
            End Get
            Set(ByVal value As TokenProvider(Of X509SecurityToken))

                serviceX509TokenProviderValue = value
            End Set
        End Property

        Public Sub New()
        End Sub 'New

        Public Overrides Function CreateClientOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return Nothing
        End Function 'CreateClientOutputFilter

        Public Overrides Function CreateClientInputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return Nothing
        End Function 'CreateClientInputFilter

        Public Overrides Function CreateServiceInputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return New CustomSecurityServerInputFilter(Me)
        End Function 'CreateServiceInputFilter

        Public Overrides Function CreateServiceOutputFilter(ByVal context As FilterCreationContext) As SoapFilter
            Return New CustomSecurityServerOutputFilter(Me)
        End Function 'CreateServiceOutputFilter

        Public Overrides Sub ReadXml(ByVal reader As XmlReader, ByVal extensions As IDictionary(Of String, Type))
            If reader Is Nothing Then
                Throw New ArgumentNullException("reader")
            End If
            If extensions Is Nothing Then
                Throw New ArgumentNullException("extensions")
            End If
            Dim isEmpty As Boolean = reader.IsEmptyElement
            MyBase.ReadAttributes(reader)
            reader.ReadStartElement("CustomSecurityAssertion")

            If Not isEmpty Then
                ' Read the contents of the <clientToken> element.
                If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "clientToken" Then
                    reader.ReadStartElement()
                    reader.MoveToContent()

                    ' Get the registed security token provider for X.509 certificate security credentials. 
                    Dim type As Type = extensions(reader.Name)
                    Dim instance As Object = Activator.CreateInstance(type)

                    If instance Is Nothing Then
                        Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type 0End.", type.AssemblyQualifiedName))
                    End If
                    Dim clientProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))

                    ' Read the child elements that provide the details about the client's X.509 certificate. 
                    clientProvider.ReadXml(reader, extensions)
                    Me.ClientX509TokenProvider = clientProvider
                    reader.ReadEndElement()
                End If
                ' Read the contents of the <serviceToken> element.
                If reader.MoveToContent() = XmlNodeType.Element AndAlso reader.Name = "serviceToken" Then
                    reader.ReadStartElement()
                    reader.MoveToContent()

                    ' Get the registed security token provider for X.509 certificate security credentials. 
                    Dim type As Type = extensions(reader.Name)
                    Dim instance As Object = Activator.CreateInstance(type)

                    If instance Is Nothing Then
                        Throw New InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type 0End.", type.AssemblyQualifiedName))
                    End If
                    Dim serviceProvider As TokenProvider(Of X509SecurityToken) = CType(instance, TokenProvider(Of X509SecurityToken))

                    ' Read the child elements that provide the details about the client's X.509 certificate. 
                    serviceProvider.ReadXml(reader, extensions)
                    Me.ServiceX509TokenProvider = serviceProvider
                    reader.ReadEndElement()
                End If
                MyBase.ReadElements(reader, extensions)
                reader.ReadEndElement()
            End If
        End Sub
        Public Overrides Function GetExtensions() As IEnumerable(Of KeyValuePair(Of String, Type))

            ' Add the CustomSecurityAssertion custom policy assertion to the list of registered
            ' policy extensions.
            Dim extensions As New List(Of KeyValuePair(Of String, Type))
            extensions.Add(New KeyValuePair(Of String, Type)("CustomSecurityAssertion", Me.GetType()))
            If (Not serviceX509TokenProviderValue Is Nothing) Then

                ' Add any policy extensions that read child elements of the <serviceToken> element
                ' to the list of registered policy extensions.
                Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = serviceX509TokenProviderValue.GetExtensions()
                If (Not innerExtensions Is Nothing) Then
                    Dim extension As KeyValuePair(Of String, Type)
                    For Each extension In innerExtensions
                        extensions.Add(extension)
                    Next
                End If
            End If
            If (Not clientX509TokenProviderValue Is Nothing) Then

                ' Add any policy extensions that read child elements of the <clientToken> element
                ' to the list of registered policy extensions.
                Dim innerExtensions As IEnumerable(Of KeyValuePair(Of String, Type)) = clientX509TokenProviderValue.GetExtensions()
                If (Not innerExtensions Is Nothing) Then
                    Dim extension As KeyValuePair(Of String, Type)
                    For Each extension In innerExtensions
                        extensions.Add(extension)
                    Next
                End If
            End If
            Return extensions
        End Function

    End Class 'CustomSecurityAssertion


    Class RequestState
        Private clientTokenValue As SecurityToken
        Private serverTokenValue As SecurityToken


        Public Sub New(ByVal cToken As SecurityToken, ByVal sToken As SecurityToken)
            clientTokenValue = cToken
            serverTokenValue = sToken
        End Sub 'New


        Public ReadOnly Property ClientToken() As SecurityToken
            Get
                Return clientTokenValue
            End Get
        End Property

        Public ReadOnly Property ServerToken() As SecurityToken
            Get
                Return serverTokenValue
            End Get
        End Property
    End Class 'RequestState 

    Class CustomSecurityServerInputFilter
        Inherits ReceiveSecurityFilter

        Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
            MyBase.New(parentAssertion.ServiceActor, False)
        End Sub 'New


        Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
            Dim clientToken As SecurityToken = Nothing
            Dim serverToken As SecurityToken = Nothing

            ' Ensure incoming SOAP messages are signed and encrypted.
            Dim elem As ISecurityElement
            For Each elem In security.Elements
                If TypeOf elem Is MessageSignature Then
                    Dim sig As MessageSignature = CType(elem, MessageSignature)
                    clientToken = sig.SigningToken
                End If

                If TypeOf elem Is EncryptedData Then
                    Dim enc As EncryptedData = CType(elem, EncryptedData)
                    serverToken = enc.SecurityToken
                End If
            Next elem

            If clientToken Is Nothing OrElse serverToken Is Nothing Then
                Throw New Exception("Incoming message did not meet security requirements")
            End If
            Dim state As New RequestState(clientToken, serverToken)

            envelope.Context.OperationState.Set(state)
        End Sub 'ValidateMessageSecurity
    End Class 'CustomSecurityServerInputFilter

    Class CustomSecurityServerOutputFilter
        Inherits SendSecurityFilter
        Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
            MyBase.New(parentAssertion.ServiceActor, False)
        End Sub 'New

        Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security)
            Dim state As RequestState = envelope.Context.OperationState.Get(Of RequestState)()

            ' Sign the message with the Web service's security token.
            security.Tokens.Add(state.ServerToken)
            security.Elements.Add(New MessageSignature(state.ServerToken))

            ' Encrypt the message with the client's security token.
            security.Elements.Add(New EncryptedData(state.ClientToken))
        End Sub 'SecureMessage
    End Class 'CustomSecurityServerOutputFilter

    Class CustomSecurityClientInputFilter
        Inherits ReceiveSecurityFilter

        Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
            MyBase.New(parentAssertion.ServiceActor, True)
        End Sub 'New

        Public Overrides Sub ValidateMessageSecurity(ByVal envelope As SoapEnvelope, ByVal security As Security)
            Dim state As RequestState
            Dim signed As Boolean = False
            Dim encrypted As Boolean = False

            ' Get the request state out of the operation state.
            state = envelope.Context.OperationState.Get(Of RequestState)()

            ' Make sure the message was signed with the server's security token.
            Dim elem As ISecurityElement
            For Each elem In security.Elements
                If TypeOf elem Is MessageSignature Then
                    Dim sig As MessageSignature = CType(elem, MessageSignature)

                    If sig.SigningToken.Equals(state.ServerToken) Then
                        signed = True
                    End If
                End If
                If TypeOf elem Is EncryptedData Then
                    Dim enc As EncryptedData = CType(elem, EncryptedData)

                    If enc.SecurityToken.Equals(state.ClientToken) Then
                        encrypted = True
                    End If
                End If
            Next elem
            If Not signed OrElse Not encrypted Then
                Throw New Exception("Response message does not meet security requirements")
            End If
        End Sub 'ValidateMessageSecurity
    End Class 'CustomSecurityClientInputFilter

    Class CustomSecurityClientOutputFilter
        Inherits SendSecurityFilter
        Private clientToken As SecurityToken
        Private serverToken As SecurityToken

        Public Sub New(ByVal parentAssertion As CustomSecurityAssertion)
            MyBase.New(parentAssertion.ServiceActor, True)
            ' Get the client security token.
            clientToken = X509TokenProvider.CreateToken(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient")

            ' Get the server security token.
            serverToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer")
        End Sub 'New

        Public Overrides Sub SecureMessage(ByVal envelope As SoapEnvelope, ByVal security As Security)
            ' Sign the SOAP message with the client's security token.
            security.Tokens.Add(clientToken)
            security.Elements.Add(New MessageSignature(clientToken))

            ' Encrypt the SOAP message with the client's security token.
            security.Elements.Add(New EncryptedData(serverToken))

            ' Encrypt the client's security token with the server's security token.
            security.Elements.Add(New EncryptedData(serverToken, "#" + clientToken.Id))

            ' Store the client and server security tokens in the request state.
            Dim state As New RequestState(clientToken, serverToken)

            ' Store the request state in the proxy's operation state. 
            ' This makes these tokens accessible when SOAP responses are 
            ' verified to have sufficient security requirements.
            envelope.Context.OperationState.Set(state)
        End Sub 'SecureMessage
    End Class 'CustomSecurityClientOutputFilter
End Namespace
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Xml;

using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Design;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;

namespace CustomPolicyAssertions
{
    class CustomSecurityAssertion : SecurityPolicyAssertion
    {
        TokenProvider<X509SecurityToken> serviceX509TokenProviderValue;
        TokenProvider<X509SecurityToken> clientX509TokenProviderValue;

        public TokenProvider<X509SecurityToken> ClientX509TokenProvider
        {
            get
            {
                return clientX509TokenProviderValue;
            }
            set
            {
                clientX509TokenProviderValue = value;
            }
        }

        public TokenProvider<X509SecurityToken> ServiceX509TokenProvider
        {
            get
            {
                return serviceX509TokenProviderValue;
            }
            set
            {
                serviceX509TokenProviderValue = value;
            }
        }


        public CustomSecurityAssertion()
            : base()
        {
        }

        public override SoapFilter CreateClientOutputFilter(FilterCreationContext context)
        {
            return new CustomSecurityClientOutputFilter(this);
        }

        public override SoapFilter CreateClientInputFilter(FilterCreationContext context)
        {
            return new CustomSecurityClientInputFilter(this);
        }

        public override SoapFilter CreateServiceInputFilter(FilterCreationContext context)
        {
            return new CustomSecurityServerInputFilter(this);
        }

        public override SoapFilter CreateServiceOutputFilter(FilterCreationContext context)
        {
            return new CustomSecurityServerOutputFilter(this);
        }


        public override void ReadXml(System.Xml.XmlReader reader, IDictionary<string, Type> extensions)
        {
            if (reader == null)
                throw new ArgumentNullException("reader");
            if (extensions == null)
                throw new ArgumentNullException("extensions");

            bool isEmpty = reader.IsEmptyElement;
            base.ReadAttributes(reader);
            reader.ReadStartElement("CustomSecurityAssertion");

            if (!isEmpty)
            {
                if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "clientToken")
                {
                    reader.ReadStartElement();
                    reader.MoveToContent();
                    // Get the registed security token provider for X.509 certificate security credentials. 
                    Type type = extensions[reader.Name];
                    object instance = Activator.CreateInstance(type);

                    if (instance == null)
                        throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));

                    TokenProvider<X509SecurityToken> clientProvider = instance as TokenProvider<X509SecurityToken>;

                    // Read the child elements that provide the details about the client's X.509 certificate. 
                    clientProvider.ReadXml(reader, extensions);
                    this.ClientX509TokenProvider = clientProvider;
                    reader.ReadEndElement();
                }
                if (reader.MoveToContent() == XmlNodeType.Element && reader.Name == "serviceToken")
                {
                    reader.ReadStartElement();
                    reader.MoveToContent();

                    // Get the registed security token provider for X.509 certificate security credentials. 
                    Type type = extensions[reader.Name];
                    object instance = Activator.CreateInstance(type);

                    if (instance == null)
                        throw new InvalidOperationException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Unable to instantiate policy extension of type {0}.", type.AssemblyQualifiedName));

                    TokenProvider<X509SecurityToken> serviceProvider = instance as TokenProvider<X509SecurityToken>;
                    // Read the child elements that provide the details about the Web service's X.509 certificate.
                    serviceProvider.ReadXml(reader, extensions);
                    this.ServiceX509TokenProvider = serviceProvider;
                    reader.ReadEndElement();
                }
                base.ReadElements(reader, extensions);
                reader.ReadEndElement();
            }
        }
        public override IEnumerable<KeyValuePair<string, Type>> GetExtensions()
        {
            // Add the CustomSecurityAssertion custom policy assertion to the list of registered
            // policy extensions.
            List<KeyValuePair<string, Type>> extensions = new List<KeyValuePair<string, Type>>();
            extensions.Add(new KeyValuePair<string, Type>("CustomSecurityAssertion", this.GetType()));
            if (serviceX509TokenProviderValue != null)
            {
                // Add any policy extensions that read child elements of the <serviceToken> element
                // to the list of registered policy extensions.
                IEnumerable<KeyValuePair<string, Type>> innerExtensions = serviceX509TokenProviderValue.GetExtensions();
                if (innerExtensions != null)
                {
                    foreach (KeyValuePair<string, Type> extension in innerExtensions)
                    {
                        extensions.Add(extension);
                    }
                }
            }
            if (clientX509TokenProviderValue != null)
            {
                // Add any policy extensions that read child elements of the <clientToken> element
                // to the list of registered policy extensions.
                IEnumerable<KeyValuePair<string, Type>> innerExtensions = clientX509TokenProviderValue.GetExtensions();
                if (innerExtensions != null)
                {
                    foreach (KeyValuePair<string, Type> extension in innerExtensions)
                    {
                        extensions.Add(extension);
                    }
                }
            }
            return extensions;
        }
        // </snippet16

    }

    class RequestState
    {
        SecurityToken clientToken;
        SecurityToken serverToken;

        public RequestState(SecurityToken cToken, SecurityToken sToken)
        {
            clientToken = cToken;
            serverToken = sToken;
        }

        public SecurityToken ClientToken
        {
            get { return clientToken; }
        }

        public SecurityToken ServerToken
        {
            get { return serverToken; }
        }
    }
    class CustomSecurityServerInputFilter : ReceiveSecurityFilter
    {
        public CustomSecurityServerInputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion.ServiceActor, false)
        {
            
        }
        public override void  ValidateMessageSecurity(SoapEnvelope envelope, Security security)
        {
            SecurityToken clientToken = null;
            SecurityToken serverToken = null;

            // Ensure incoming SOAP messages are signed and encrypted.
            foreach (ISecurityElement elem in security.Elements)
            {
                if (elem is MessageSignature)
                {
                    MessageSignature sig = (MessageSignature)elem;
                    clientToken = sig.SigningToken;
                }

                if (elem is EncryptedData)
                {
                    EncryptedData enc = (EncryptedData)elem;
                    serverToken = enc.SecurityToken;
                }
            }

            if (clientToken == null || serverToken == null)
                throw new Exception("Incoming message did not meet security requirements");

            RequestState state = new RequestState(clientToken, serverToken);

            envelope.Context.OperationState.Set(state);
        }
    }

    class CustomSecurityServerOutputFilter : SendSecurityFilter
    {

        public CustomSecurityServerOutputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion.ServiceActor,false )
        {
        }

        public override void SecureMessage(SoapEnvelope envelope, Security security)
        {
            RequestState state = envelope.Context.OperationState.Get<RequestState>();

            // Sign the message with the Web service's security token.
            security.Tokens.Add(state.ServerToken);
            security.Elements.Add(new MessageSignature(state.ServerToken));

            // Encrypt the message with the client's security token.
            security.Elements.Add(new EncryptedData(state.ClientToken));
        }
    }
    class CustomSecurityClientInputFilter : ReceiveSecurityFilter
    {
        public CustomSecurityClientInputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion.ServiceActor,true )
        {

        }

        public override void ValidateMessageSecurity(SoapEnvelope envelope, Security security)
        {
            RequestState state;
            bool signed = false;
            bool encrypted = false;

            // Get the request state out of the operation state.
            state = envelope.Context.OperationState.Get<RequestState>();

            // Make sure the message was signed with the server's security token.
            foreach (ISecurityElement elem in security.Elements)
            {
                if (elem is MessageSignature)
                {
                    MessageSignature sig = (MessageSignature)elem;

                    if (sig.SigningToken.Equals(state.ServerToken))
                        signed = true;
                }

                if (elem is EncryptedData)
                {
                    EncryptedData enc = (EncryptedData)elem;

                    if (enc.SecurityToken.Equals(state.ClientToken))
                        encrypted = true;
                }
            }

            if (!signed || !encrypted)
                throw new Exception("Response message does not meet security requirements");
        }
    }
    class CustomSecurityClientOutputFilter : SendSecurityFilter
    {
        SecurityToken clientToken;
        SecurityToken serverToken;

        public CustomSecurityClientOutputFilter(CustomSecurityAssertion parentAssertion)
            : base(parentAssertion.ServiceActor,true )
        {
            // Get the client security token.
            clientToken = X509TokenProvider.CreateToken(StoreLocation.CurrentUser, StoreName.My, "CN=WSE2QuickStartClient");

            // Get the server security token.
            serverToken = X509TokenProvider.CreateToken(StoreLocation.LocalMachine, StoreName.My, "CN=WSE2QuickStartServer");
        }

        public override void SecureMessage(SoapEnvelope envelope, Security security)
        {
            // Sign the SOAP message with the client's security token.
            security.Tokens.Add(clientToken);
            security.Elements.Add(new MessageSignature(clientToken));

            // Encrypt the SOAP message with the client's security token.
            security.Elements.Add(new EncryptedData(serverToken));

            // Encrypt the client's security token with the server's security token.
            security.Elements.Add(new EncryptedData(serverToken, "#" + clientToken.Id));

            // Store the client and server security tokens in the request state.
            RequestState state = new RequestState(clientToken, serverToken);

            // Store the request state in the proxy's operation state. 
            // This makes these tokens accessible when SOAP responses are 
            // verified to have sufficient security requirements.
            envelope.Context.OperationState.Set(state);
        }
    }
}

See Also

Tasks

How to: Create a Custom Policy Assertion that does not Secure SOAP Messages
How to: Secure an Application Using a Custom Policy Assertion

Reference

SecurityPolicyAssertion
ReceiveSecurityFilter
SendSecurityFilter
PolicyAssertion
SoapFilter

Concepts

Turnkey Security Assertions

Other Resources

Custom Policy Assertions
Securing a Web Service