Search code examples
web-servicescookiescoldfusionhttprequestcoldfusion-9

Add cookie to HTTP header for SOAP call in ColdFusion


I basically want to add the ASP.NET_SessionId cookie to my HTTP request header when calling a SOAP web service through ColdFusion.

The web service is registered in the OnApplicationStart function of the Application.cfc component in ColdFusion.

<cfscript>
    objSoapHeader = XmlParse("<wsse:Security mustUnderstand=""true"" xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""><wsse:UsernameToken><wsse:Username>MY_USERNAME</wsse:Username><wsse:Password>MY_PASSWORD</wsse:Password></wsse:UsernameToken></wsse:Security>");
    Application.UserWebService = CreateObject("webservice","MY_URL/UserService.asmx?WSDL");
    addSOAPRequestHeader(Application.UserWebService,"","",objSoapHeader,true);
</cfscript>

My web service is called as such:

<cfset Result = "#Application.UserWebService.SomeFunction("1", "DATA")#">

In order for the .Net server (where the web services are located) to remember my session state, I must pass the ASP.NET_SessionId cookie in the HTTP request header, but have no idea if this is even possible in ColdFusion.

I've researched for several hours but nothing has come of it as of yet, so has anyone successfully managed to pull this off?


Solution

  • Short Answer:

    For CF9 / Axis1 try enabling sessions on the web service object.

    ws = createObject("webservice", "http://localhost/MyWebService.asmx?wsdl");
    ws.setMaintainSession( true );
    

    For CF10+ / Axis2, see longer answer below:


    (Disclaimer: Using cfhttp might be simpler, but I was curious and did some digging ..)

    From what I have read, since CF10+ uses Axis2 for web services it should be possible to use the underlying methods to maintain session state through HTTP cookies.

    Using the the links above, I put together a quick POC using a basic web service and was able to extract the cookie header from the web service client response:

    // make initial request
    ws = createObject("webservice", "http://localhost/MyWebService.asmx?wsdl");
    ws.firstMethod();
    
    // For maintainability, use constants instead of hard coded strings
    wsdlConstants = createObject("java", "org.apache.axis2.wsdl.WSDLConstants");
    
    // Extract headers 
    operation = ws._getServiceClient().getLastOperationContext();
    context = operation.getMessageContext( wsdlConstants.MESSAGE_LABEL_IN_VALUE  );
    headers = context.getProperty( context.TRANSPORT_HEADERS );
    

    Then set the cookie and instruct the web service client to send it with subsequent requests:

    if ( structKeyExists(headers, "Set-Cookie") ) {
        // include http cookies with request
        httpConstants = createObject("java", "org.apache.axis2.transport.http.HTTPConstants");
        options = ws._getServiceClient().getOptions();
        options.setManageSession( true );
        options.setProperty( httpConstants.COOKIE_STRING, headers["Set-Cookie"] );
    }
    
    // ... more requests
    ws.secondMethod();
    ws.thirdMethod();
    

    NB: Side note, I noticed you are storing the instance in the shared Application scope. Just keep in mind web service instances are probably NOT thread safe.