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?
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.
How to set Cookies in ColdFusion SOAP requests - (circa 2006) - Written for a much older version of CF/Axis, so some of it is outdated, but it still provides a good overview of the general concept.
Maintain session in Axis2
Java axis web service client setMaintainSession on multiple services (cookies?)
Axis2 Manage Session Cookie Manually
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.
Inside your CFHPPT tags, set the cookie with CFHTTPPARAM
Related
Need help on the following questions regarding cookie
I'm developing a standalone jar which access a http site inside the code. When i access the http site will the cookie will be stored in the client machine ??
When the cookie will be saved in client's machine ?
The cookie will be stored only when we access web application via browser or via any library and executing http request
When and how the cookie can be enabled or disabled in a client's machine.
Thanks.
Your java application will need create a cookie store and link it to the HttpClient. For example
CookieStore cookieStore = new BasicCookieStore();
// Populate cookies if needed
BasicClientCookie cookie = new BasicClientCookie("name", "value");
cookie.setDomain(".mycompany.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);
// Set the store
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
Reference: https://hc.apache.org/httpcomponents-client-ga/tutorial/html/statemgmt.html
I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.
I am badly stuck with a SOAP based integration using Axis2 framework for generation of client stubs from the Server WSDL. The scenario is as follows :
There is always a login API call first, which gives a Success response in SOAP body and Temporary Redirect in HTTP header. Also provides a URL which contains the session ID in the Location field of HTTP Header.
The next API call is required to be made at this redirect location. IN THE SAME TCP CONNECTION, for getting a proper response.
Now, the problem is, as a part of Webservice implementation using Axis2 generated stubs, I need to reload this redirect URL and re-instantiate it as --- "stub=new Stub(newurl)"
As soon as this is done, it creates a new TCP connection and so, the next request gives the response as "session ID invalid" because it goes out-of-sync with login API.
I have tried everything mentioned as a solution in this forum and nothing is working out.
For e.g --
MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
HttpClient httpClient = new HttpClient(httpConnectionManager);
ServiceClient serviceClient = stub._getServiceClient();
Options opts = stub._getServiceClient().getOptions();
opts.setTo(new EndpointReference(prop.getProperty("target_end_point_url")));
opts.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
opts.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
serviceClient.setOptions(opts);
stub._setServiceClient(serviceClient);
Similarly, I have tried many other options too. But it's not helpful at all.
Faced exactly the same issue.
Following steps solved the issue.
1. Using HttpClient, perform login. Don't use stub object to perform login.
2. Use the Location Header URL, to create new stub object i.e. stub = new Stub(locationURL). (Your existing options setting should be retained.)
3. There is a default timeout, by which server disconnects the TCP connection. In my case it was 50 seconds. Hence as soon as i performed login in step 1, i execute a timer every 40 seconds, to send an empty requests to new Location URL using HeadMethod of same HttpClient object.
I am using apache axis2 server webservies, Basically I am sending xml response to android client through webservices. Here I need to maintain the session since the services per user basis. I know maintaining session in webservices is bad idea, but cant avoid it.
Actually I need to generate random unique string when user invoke first service from android client, that random string going to be used as session id. This session id, i need to set in http custom header, so that android client can able to get it and can send it subsequent requests as well.
I want to know whether any API is available in axis2 to set custom header information on http headers. Same way I need to read the http header, so that next request I can get the session id from header.
Can anyone advice me regarding this?? Thanks
-Ravi
Dead link on #Martin Dürrmeier's answer, here's a snapshot of the webpage that i've found on web.archive.org : Axis2 - Setting custom HTTP Headers on a response, it helped me.
Here's the lines needed :
MessageContext responseMessageContext =
MessageContext.getCurrentMessageContext().getOperationContext().getMessageContext(
WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
List<Header> headers = new ArrayList<Header>();
headers.add(new Header(HTTPConstants.HEADER_CONTENT_ENCODING, "identity"));
responseMessageContext.setProperty(HTTPConstants.HTTP_HEADERS, headers);
I am trying to understand what things happen in the background when using a website OR basically what are the things that happen when a user interacts with a browser. I understand that this is a huge list and highly dependent on architecture and user actions etc, I am just trying to get a feel of major things and flush my misunderstandings and also use this to read more about stuff I don't understand.
As an exercise I am trying to note down things that happen in the background with respect to users action in a browser. Here is my attempt at this bit open ended but fun question:
User enters a url => browser checks if
available in browser cache => DNS look
up [root dns lookup => recursive dns
=> get ip ] => establish a tcp connection => send http req => get
the static page from web server=> if
authentication is required that
happens [either read cookies from
browser OR ask user to enter
credentials] => somehow gets the
dynamic elements as well [how ? ,
there is some lazy initilization here
?] => Then user performs some
action[clicks a link or something] =>
check browser cache => if not avail
[take the input parameters and embed
in the url in some manner [may be
encrypt some things if required] =>
hits a load balancer => directed to a
application server [depending on how
the LB selects a host] => application
server cache is checked [memcached or
some kind of caching, not sure if this
"normally" happens here or at some
other level] => application server
tries to understand the request [if
its a service listening on some port,
http port 80 it will get the URL and
parse to perform some operations] =>
database is queried if required to =>
there might again be connection
mgmt/caching/parallel queries etc here
=> database returns back the result to app server => app server creats a
result payload and headers [http] =>
sends it to browser for rendering =>
browser cache is updated => user
reacts to the response.
I have not considered retries/failures and how they are handled, but I would like to get some input there as well in a general sense
Note:
I am looking at things in general, I am sure that few companies might do it in different way etc etc. I will like to hear alternatives as well though!.
This is an effort to try and get more
perspective and read on few things
that will help me in general.
Clearly I have made an honest attempt
I also hope this would help others
looking at the question in general to
learn something new.
I am not asking
for opinions etc, so this aint a
completely open ended question [not
everything is right though there are
many options]
Thanks !
There is no difference between static or dynamic for browser. Browser makes HTTP request and gets HTTP response. If response is an HTML page, then browser renders HTML ,applies styles, and executes JavaScript code that come with page. This page can by dynamic or static - browser don't care! The side is care - is server side. If page is static, than HTTP server will just take page from disk and send it to client as HTTP response. If page is dynamic, than HTTP server will call some application and will ask this application to give requested resource. This application can be an PHP module for Apache(http server), or ASP.net for IIS, or even your C++ code that will generate any content you want.
How exactly page or resource (HTTP response can be also xml, or image etc) will be constructed depends on used application (server side technology).
As example, if you are using PHP - HTTP server will detect that requested resource has extension .php, server will pass this PHP file to PHP module for processing, and result will be sent to HTTP client(browser) as response.
When user perform some action, this is again just usual HTTP request. HTTP method GET and POST (look for article about HTTP on Wikipedia) is used to pass some input from server to client. Page can contain some heavy JS, that will make page look more like desktop application (rich controls, dynamically reacting on user action without request to server, or communicate with server in background), but this is not necessary for web application to be web application (for web site to by dynamic). It can be good old static HTML with HTML forms, and some server side code.
Web application is abstract entity that may consist from many HTTP resources (different URLs for server to response). Web application also is client-side code that communicates with server-side code thru HTTP with help of HTTP client(browser) and HTTP server. Web application is not some stand alone part, that only comes to work when user perform some action.
Web-service may fits this description - as thing that usually don't care about pages, and comes only when some action required. Its special type of web application, that expose some API thru HTTP(usually). You can request some resource, and pass some parameter, and you will get response with some result. It's same web application but without pages. But web-service usually part of big web application with pages, or even other part of same web-application (depending on how you look at this). It can be same server-side technology, and same HTTP server. And it's not necessary to create web-service if you want to make some web-application (dynamic web site).
Server-side part of web application can also communicate with some database, but it's not necessary too.
There can be real database, or just some text files on disk. And browser, client side code and HTTP server also don't care about database or source where server side code takes data.
Cache, load balancer, etc - it's just additional elements that usually are transparent for all this general stuff.
Cookies is passed with every HTTP request to HTTP server, and if requested resource is not static page, that HTTP server will pass them further to server-side code/application(part). And its usually how authentication and authorization works - cookies has contain info about session, and there is some data associated with session contains on server side - it can be ID of user, so server-side code will recognize user on every request.