I’ve been working on securing web services and SOAP extensions for some time now. First, when I read about SOAP Extensions, it sounded like Greek and Latin to me. But it’s a very simple concept, which I failed to understand in the beginning. So, in this article, I would like to share whatever I understood about SOAP Extensions.
Web Services in the simplest terms are function calls over the Internet. They are reusable applications that expose an interface, which can be accessed over the Internet. Communication between the service provider and the client can take place through SOAP messages (the other two being HTTP-GET and HTTP-POST).
Life Cycle of a SOAP Message
To understand SOAP extensions, we must first know how SOAP messages are used in the communication. When a client invokes/calls a web service, it sends a request to the web service. This request is serialized into a SOAP message and sent over the network. On reaching the server side, this SOAP message is deserialized and the web service reads the request from the client. Depending on the client request, web service performs required operations and generates responses. This response is serialized into SOAP message at the server and deserialized at the client side. Similarly, the SOAP message is serialized at the server and deserialized at the client side when the response is sent from the server to the client.
Thus the SOAP message goes through a process of serialization and deserialization both at the client and the server side. The various stages of SOAP messages are available in the
SOAPMessageStage enumeration. The members of the enumeration includes:
(The names being self-explanatory). Now that we have understood the path for SOAP messages, let's take a look at SOAP Extensions.
SOAP Extensions are components that can access the SOAP messages. Think of them as objects that sit on the HTTP pipeline who can pick the SOAP messages at each stage and manipulate them.
When the HTTP request comes from the client, it is handled by aspnet_isapi.dll. The appropriate handler for web services will be called and the web method will be invoked. It is during this stage where the SOAP Extension comes into picture. The SOAP Extension can access the SOAP message before and after calling the web method. Thus we now know in a vague manner what a SOAP extension is and where it fits in the life cycle of a SOAP message.
SOAP Extensions can be used for a number of purposes. They can be used to secure web services, compress the verbose SOAP messages, log messages etc. In this article, we will see how to encrypt the SOAP message and send it over the network using SOAP Extensions.
To build a SOAP Extension, we must create a class that inherits from
System.Web.Services.Protocols.SaopExtension. This is an abstract class and our derived class should implement the functionalities. The functions include:
Public Overrides Function ChainStream(ByVal stream As Stream) _As Stream
Public Overloads Overrides Function GetInitializer(ByVal methodInfo _
As LogicalMethodInfo, ByVal attribute As _
SOAPExtensionAttribute) As Object
Public Overloads Overrides Function GetInitializer(ByVal _
WebServiceType As Type) As Object
Public Overrides Sub Initialize(ByVal initializer As Object)
Public Overrides Sub ProcessMessage(ByVal message As SOAPMessage)
Now, let us go into each function.
Initializing SOAP extension specific data
The SOAP extension class provides two methods to initialize data:
GetInitializer and the
GetInitializer method is called only once when you call the web service or the web service method.
GetInitializer method has two overloads. The first overload is called when the extension is configured by web.config, the second is called if the extension is configured by a
SOAPExtensionAttribute on a specific WebMethod. This data in the
Getinitializer method will be cached by the ASP.NET infrastructure. This cached data will be passed to a SOAP extension whenever the SOAP extension runs with the XML Web service or service method in the
Initialize method. The
Initialize method will be called every time the SOAP extension runs with the web method. In cases where we do not want any initialization of data, we can return
null. I.e., basically:
GetInitializer - called only once.
Initialize - called whenever a request comes in.
Processing the SOAP Request
The heart of the SOAP Extension lies in processing the SOAP message. This is handled by the
ProcessMessage function. The input parameter to this method is the SOAP message. This method allows us to manipulate the SOAP message. We can also get information about what states the SOAP message belongs to and accordingly manipulate them.
Public Overrides Sub ProcessMessage(ByVal message As SoapMessage)
Select Case message.Stage
arr = objEnSoap.EncryptSoap(arr)
arr = objEnSoap.DecryptSoap(arr)
Throw New Exception("invalid stage")
As you can see from the code, I have called the
Decrypt method in the
ProcessMessage function. These functions are defined in the code, which can be used to encrypt or decrypt the SOAP messages. Here, I have used DES Encryption by using the standard library provided by .NET. This function returns an encrypted SOAP message, which is sent over the network. Similarly, the
Decrypt method will also be called when the SOAP reaches the other end. Moreover, I have also added functions to log the SOAP messages (both encrypted and XML).
Now, another question that may come to our mind is why use a SOAP extension to encrypt the SOAP message, why not use SSL. SSL can also be used, but it provides end-to-end communication and not point-to-point communication.