How to Use SOAP Headers to Limit the Lifespan of a WebService Call
by
, 30-Dec-2011 at 06:11 AM (15821 Views)
In this blog I will show you how you can limit the amount of time that an application can call a webservice function. It is a small contribution to security and helps you against unwanted webservice calls.
SOAP Headers
A SOAP based WebService call always contains a body section and optionally can contain a header section. The use of a SOAP header section on both the Visual DataFlex server as well as client side is good documented in the help provided with the product. The good thing of the header section is that one cannot know if it is required and what the contents should be if someone looks at the WSDL. So only if someone intercepts the traffic between server and client it could be known.
A Token Function
The idea of this blog is to create a token that needs to be passed on the next webservice call and this token should only be valid for a certain amount of time. So let us create a token to do that.
As you can see it is a very simple function and if you like you can make it much more complex. Of course you can make the description empty or make the name not so clear and both make it less clear to someone that does not know. The StrToHex function can be found in the conversions library. Since the token has a short lifetime span you either need to call the CreateToken function often or return the next token in the header by the server.Code:{ Published = True } { Description = "Returns a communication token." } Function CreateToken Returns String DateTime dtNow String sToken Move (CurrentDateTime ()) to dtNow Get StrToHex of oHexHandler dtNow to sToken Function_Return sToken End_Function
Passing the Retrieved Token
Now the client side that calls our webservice functions need to pass this token with each call. The following code shows how to do that from a Visual DataFlex application.
You can make it less clear to a hacker by renaming "Token" to something like "Flower" or "Christmas" or so.Code:Get wsCreateToken of oWSMyService to sToken Send ClearSoapHeaders of oWSMyService // Removes a header node that was in memory from the last call Get Create (RefClass (cXmlDomDocument)) to hoXml // Creates an XML object Get CreateDocumentElementNS of hoXml "http://www.dataaccess.com/secure" "Token" to hoRoot Set psText of hoRoot to sToken Send AddSoapHeaderNode of oWSMyService hoRoot // destroy the XML object Send Destroy of hoXml
Testing the Passed Token
At server side we need to read the SOAP header section and validate the passed token. The following code does that and the function needs to be called from each of your webservice functions.
The above function returns true if the token is present and the time difference between the test and the time of the requested token is less than 5,000 milliseconds. For debugging your webservices I suggest you make the time span bigger (lets say 50,000 milliseconds. The code that calls our ValueRequest function could be:Code:Function ValidateRequest Returns Boolean Handle hoXml hoRoot hoNode String sToken Boolean bIsId bValidRequest DateTime dtNow dtToken TimeSpan tsDiff // get request headers Get SoapHeaderRequestNode to hoXml If (hoXml <> 0) Begin Get DocumentElement of hoXML to hoRoot // should be SOAP header node Get FirstChild of hoRoot to hoNode // process all headers nodes While (hoNode <> 0) Get IsElementNS of hoNode "http://www.dataaccess.com/secure" "Token" to bIsId If (bIsId) Begin Get pstext of hoNode to sToken End Get NextNode of hoNode to hoNode Loop // when done, destroy the XML object Send Destroy of hoXml End If (sToken <> "") Begin Get HexToStr of oHexHandler sToken to dtToken Move (CurrentDateTime ()) to dtNow Move (dtNow - dtToken) to tsDiff Move (SpanTotalMilliseconds (tsDiff) < 5000) to bValidRequest End Function_Return bValidRequest End_Function
This is my last contribution for 2011 and I wish all of you a happy 2012!Code:{ Published = True } { Description = "Returns a list of contact names" } Function ContactNames Boolean bActive Returns String[] String[] sNames Boolean bValidRequest Get ValidateRequest to bValidRequest If (bValidRequest) Begin