Message Validation

patterns & practices Developer Center

  • How to: Protect Your Service from Malicious Messages
  • How to: Protect Your Service from Malicious Input
  • How to: Protect Your Service from Denial of Service Attacks
  • How to: Validate Parameters with Parameter Inspectors
  • How to: Validate Parameters with Message Inspectors Using Schemas
  • How to: Validate Data Contracts with Message Inspectors Using Schemas
  • How to: Validate Message Contracts with Message Inspectors Using Schemas
  • How to: Use Regular Expressions to Validate Format, Range, and Length in Schemas
  • How to: Validate Inbound Messages on a Service
  • How to: Validate Outbound Messages on a Service
  • How to: Validate Outbound Messages on the Client
  • How to: Validate Inbound Messages on the Client
  • How to: Validate Input Parameters
  • How to: Validate Output Parameters

How to: Protect Your Service from Malicious Messages

Use schema validation to validate and protect your service from maliciously formed messages. Validation of messages with schemas can protect parameters and/or fields in operation, data, and message contracts. Use schema validation to validate for format, range, type, and length. Using schema validation allows separation of business code from validation logic. It also allows validation of message and data contracts, which include several fields. Complex types in parameters can also be validated with schemas. Without scehemas, such validation can often require writing complex validation code.

Additional Resources

How to: Protect Your Service from Malicious Input

Use schemas to validate your service against malicious input. You can protect parameters in operation contracts, and fields in message and data contracts. The parameters in operation contracts can be simple or complex types. This protection level will require that you implement message inspectors to be used by your service and/or by the clients that consume your service. You can also protect your service by validating the parameters in the operation contracts. This protection level will require that you implement parameter inspectors to be used by your service and/or the clients that consume your service. You can do client-side and service-side validation for both schema and parameter validation.

Additional Resources

How to: Protect Your Service from Denial of Service Attacks

Protect against denial of service (DoS) attacks by limiting message sizes, and by using quotas to restrict memory consumption by WCF.

Restrict the message size that is processed by WCF by using the maxReceivedMessageSize configuration present in the bindings, as shown below:

<binding name="wsHttpEndpointBindingconfig" maxReceivedMessageSize="65535">
     <security>
      <message negotiateServiceCredential="false" />
     </security>
</binding>

Restrict the buffer size used by WCF by using the maxBufferPoolSize configuration present in the bindings, as shown below:

<binding name="wsHttpEndpointBindingconfig" maxBufferPoolSize="524287"
         maxReceivedMessageSize="65535">
     <security>
      <message negotiateServiceCredential="false" />
     </security>
</binding>

In streaming scenarios, use the reader quotas to limit the size of arrays with maxArrayLength, the length of the string in XML elements with maxStringContentLength, the maximum depth of the XML node with maxDepth, the maximum bytes to be read with maxBytesPerRead, and the maximum number of characters in a table with maxNameTableCharCount.

<basicHttpBinding>
        <binding name="BasicBindingConfiguration">
          <readerQuotas maxDepth="2" maxStringContentLength="200" maxArrayLength="2000"
            maxBytesPerRead="1000" maxNameTableCharCount="1000" />
          <security mode="Transport">
            <transport clientCredentialType="None" />
          </security>
        </binding>
 </basicHttpBinding>

How to: Validate Parameters with Parameter Inspectors

Perform the following steps to validate parameters with parameter inspectors:

  1. Create a class that implements the validation logic. This class has to derive from IParameterInspector. The class has the following characteristics:
    • It implements the AfterCall() and BeforeCall() methods, both of which will have the validation logic.
    • When used as part of the service, BeforeCall() will be invoked before the parameters are dispatched to the service operation. AfterCall() will be invoked after the service has processed the call and is returning a the response to the client. Use BeforeCall() to validate your input parameters, and use AfterCall() to validate your output parameters.
    • When used as part of the client, BeforeCall() will be invoked before calling the service, and **AfterCall()**will be invoked before the service's response is dispatched to the client code. Use AfterCall() to validate the response from the service, and use BeforeCall() to validate input parameters before calling the service.
  2. Create a class that implements a custom endpoint behavior. This class derives from IEndpointBehavior, which the service and/or client endpoint will use as a configuration extensibility point for the endpoint. This class has the following characteristics:
    • It implements ApplyClientBehavior() to add the ParamaterInspector to the client operation and enable client-side validation.
    • It implements ApplyDispatchBehavior() to add the ParameterInspector to the dispatch operation and enable service-side validation.
    • It verifies that it is enabled in the configuration before adding the ParameterInspector to the client or dispatch run time.
  3. Create a class that implements a custom configuration element. This class derives from BehaviorExtensionElement. This class allows you to expose the endpoint configuration in WCF as a behavior element extension, which can be used by the service as an endpoint behavior configuration. This class has the following characteristics:
    • It implements CreateBehavior() to create an instance of the ValidationBehavior class.
    • It implements BehaviorType() to return the ValidationBehavior type. This allows the custom behavior to be exposed in the service or client configuration sections.
  4. Add the custom behavior to the configuration file. Add the custom behavior element to the behavior element extension items so that it can be used by the endpoint behavior. You add it in the configuration file by using the configuration tool to browse to the assembly and then selecting your custom behavior type.
  5. Create an endpoint behavior and map it to use the custom behavior. The custom behavior is the extensibility point containing the parameter validation. The behavior is instantiated by the assembly implementing the parameter inspector logic.
  6. Configure the service endpoint to use the endpoint behavior. Configure the endpoint to use the endpoint behavior that is using the parameter inspector.

Additional Resources

How to: Validate Messages with Message Inspectors Using Schemas

Perform the followings steps to validate messages with message inspectors using schemas:

  1. Create a class that implements the validation logic. To do client-side validation, this class should derive from IClientMessageInspector. To do server-side validation, this class should derive from IDispatchMessageInspector. Derive from both interfaces if you want to do both client-side and server-side validation. This class implements the AfterReceiveRequest(), BeforeSendReply(), BeforeSendRequest(), and AfterReceiveReply() methods. This class has the following characteristics:
    • On the dispatcher: AfterReceiveRequest will be implemented when inbound messages are received by the dispatcher, before the operation is invoked and deserialization of messages has occurred. If the message is encrypted, decryption will take place first. BeforeSendReply will be implemented when outbound messages are to be sent back to the client, after the operation is invoked and serialization has occurred. If the message is encrypted, encryption will not take place.
    • On the client: BeforeSendRequest will be implemented when outbound messages are sent by the client, after serialization has occurred. If a message is encrypted, encryption will not take place. AfterReceiveReply will be implemented when inbound messages are received by the client, before deserialization of the message has occurred. If the message is encrypted, decryption will take place first.
  2. Create a class that implements a custom endpoint behavior. This class derives from IEndpointBehavior, which the service and/or client endpoint will use as a configuration extensibility point for the endpoint. This class has the following characteristics:
    • It implements ApplyClientBehavior() to add the ParamaterInspector to the client operation and enable client-side validation.
    • It implements ApplyDispatchBehavior() to add the ParameterInspector to the dispatch operation and enable service-side validation.
    • It verifies that it is enabled in the configuration before adding the ParameterInspector to the client or dispatch run time.
  3. Create a class that implements a custom configuration element. This class derives from BehaviorExtensionElement, which allows you to expose the endpoint configuration in WCF as a behavior element extension that can be used by the service as an endpoint behavior configuration. This class has the following characteristics:
    • It implements CreateBehavior() to create an instance of the ValidationBehavior class.
    • It implements BehaviorType() to return the ValidationBehavior type. This allows the custom behavior to be exposed in the service or client configuration sections.
  4. Add the custom behavior to the configuration file. Add the custom behavior element to the behavior element extension items, so that it can be used by the endpoint behavior. You add it in the configuration file by using the configuration tool to browse to the assembly and then selecting your custom behavior type.
  5. Create an endpoint behavior and map it to use the custom behavior. The custom behavior is the extensibility point containing the parameter validation. The behavior is instantiated by the assembly implementing the parameter inspector logic.
  6. Configure the service endpoint to use the endpoint behavior. Configure the endpoint to use the endpoint behavior that is using the message inspector.

Additional Resources

How to: Validate Data Contracts with Message Inspectors Using Schemas

Perform the following high-level steps to validate data contracts passed to operations in WCF:

  1. Create a message inspector to perform schema validation.
  2. Create a schema file to validate the fields of the data contract with facets in the schema file.

See the following example, in which the CustomerData complex type is validated by using CustomerN and CustIDLimitor. This example limits integers to a value no greater than 5, and the string can be no longer than five characters.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="http://Microsoft.PatternPractices.WCFGuide" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://Microsoft.PatternPractices.WCFGuide">
  <xs:element name="GetData">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="CustomerInfo" 
                    nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="CustomerData">
    <xs:sequence>
      <xs:element name="CustomerID" type="tns:CustIDLimitor">
      </xs:element>
      <xs:element name="text" type="tns:CustomerN">
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="CustomerN">
    <xs:restriction base="xs:string">
      <xs:minLength value="1" />
      <xs:maxLength value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CustIDLimitor">
    <xs:restriction base="xs:int">
      <xs:minInclusive value="1" />
      <xs:maxInclusive value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="GetDataResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="GetDataResult" 
                    nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Additional Resources

How to: Validate Message Contracts with Message Inspectors Using Schemas

Perform the following steps to validate message contracts passed to operations in WCF:

  1. Create a message inspector to perform schema validation.
  2. Create a schema file to validate the fields of the message contract with facets in the schema file.

See the following example, in which the message contract CustomerData is validated by using CustomerN and CustIDLimitor. This example limits integers to a value no greater than 5, and the string can be no longer than five characters.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="http://Microsoft.PatternPractices.WCFGuide" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://Microsoft.PatternPractices.WCFGuide">
  <xs:element name="GetData">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="CustomerInfo" 
                    nillable="false" type="tns:MessageData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="CustomerData">
    <xs:sequence>
      <xs:element name="CustomerID" type="tns:CustIDLimitor">
      </xs:element>
      <xs:element name="text" type="tns:CustomerN">
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="CustomerN">
    <xs:restriction base="xs:string">
      <xs:minLength value="1" />
      <xs:maxLength value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CustIDLimitor">
    <xs:restriction base="xs:int">
      <xs:minInclusive value="1" />
      <xs:maxInclusive value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="GetDataResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="GetDataResult" 
                    nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Additional Resources

How to: Use Regular Expressions to Validate Format, Range, and Length in Schemas

Use regular expressions in schemas to validate format, range, or length. This allows you to use complex validation logic without needing to implement the code. It also allows decoupling of the validation logic from the business logic. The example schema below exemplifies the validation of integers with values between 1 and 5, the string of length 5, and a Social Security Number (SSN) and ZIP code with good formats:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="http://Microsoft.PatternPractices.WCFGuide" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://Microsoft.PatternPractices.WCFGuide">
  <xs:element name="GetData">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="CustomerInfo" 
                    nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="CustomerData">
    <xs:sequence>
      <xs:element name="CustomerID" type="tns:CustIDLimitor">
      </xs:element>
      <xs:element name="text" type="tns:CustomerN">
      </xs:element>
      <xs:element name="socialSecurity" type="tns:SSN">
      </xs:element>     
      <xs:element name="custZipCode" type="tns:CustomerN">
      </xs:element>          
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="CustomerN">
    <xs:restriction base="xs:string">
      <xs:minLength value="1" />
      <xs:maxLength value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CustIDLimitor">
    <xs:restriction base="xs:int">
      <xs:minInclusive value="1" />
      <xs:maxInclusive value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="SSN">
    <xs:restriction base="xs:token">
      <xs:pattern value="[0-9]{3}-[0-9]{2}-[0-9]{4}"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="us-zipcode">
    <xs:restriction base="xs:string">
      <xs:pattern value="[0-9]{5}(-[0-9]{4})?"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="GetDataResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="GetDataResult" 
                    nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

How to: Validate Inbound Messages on a Service

Implement the AfterReceiveRequest method of the message inspector's IDispatchMessageInspector interface in order to validate inbound messages on a service. This allows you to validate the message after the request has arrived but before service operation invocation and deserialization.

object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
    try
    {
        validateMessage(ref request);
    }      
    catch (FaultException e)
    {
        throw new FaultException<string>(e.Message);
    }
    return null;   
}

Additional Resources

How to: Validate Outbound Messages on a Service

Implement the BeforeSendReply method of the message inspector's IDispatchMessageInspector interface in order to validate outbound messages on a service. This allows you to validate the message before sending the response to the client and before service operation invocation and serialization.

void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
    try
    {
        validateMessage(ref reply);                
    }
    catch (FaultException fault)
    {
        // if a validation error occurred, the message is replaced
        // with the validation fault.
        reply = Message.CreateMessage(reply.Version, new FaultException("validation error in reply message").CreateMessageFault() , reply.Headers.Action);
    }
}

Additional Resources

How to: Validate Outbound Messages on the Client

Implement the BeforeSendRequest method of the message inspector's IClientMessageInspector interface in order to validate outbound messages on the client. This allows you to validate the message after serialization but before sending the request to the service.

object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
    validateMessage(ref request);
    return null;
}    

Additional Resources

How to: Validate Inbound Messages on the Client

Implement the AfterReceiveReply method of the message inspector's IClientMessageInspector interface in order to validate inbound messages on the client. This allows you to validate the message after the client response has arrived but before deserialization and before returning the data to the client application.

void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
 {
     validateMessage(ref reply);               
 }

Additional Resources

How to: Validate Input Parameters

Implement the BeforeCall() method on the parameter inspector to validate input parameters on a client or service. Inside BeforeCall(), implement the validation logic to validate the parameters.

public class ValidationParameterInspector : IParameterInspector
{
  public object BeforeCall(string operationName, object[] inputs)
  { …    }
}

Additional Resources

How to: Validate Output Parameters

Implement the AfterCall() method on the parameter inspector to validate output parameters on a client or service. Inside AfterCall(), implement the validation logic to validate the parameter.

public class ValidationParameterInspector : IParameterInspector
{
   public void AfterCall(string operationName, object[] outputs, 
               object returnValue, object correlationState)      
   { …    }
}

Additional Resources