Tuesday, September 12, 2006

Handling J2EE session with cookies disabled

Someone recently reported that when cookies are disabled and J2EE session is enabled, his sessions are not maintained in case of POST request. As per that, CF or rather the app server always creates a new session everytime. His code looked like


<form method="post" action="test.cfm?#session.urltoken#">
...
<input type="submit" value="Submit" >
</form>


can you see whats wrong with above code?

As per the Servlet spec of J2EE, when cookies are disabled, session is maintained by url rewriting and that is done by appending ';jsessionid=' to the URI. Note the semicolon ';' before 'jsessionid'.

In the above code, it is appending session.urltoken which looks like 'CFID=1600&CFTOKEN=59663989&jsessionid=2830a9edcf6f794ff481'. Therefore the url becomes "test.cfm?CFID=1600&CFTOKEN=59663989&jsessionid=2830a9edcf6f794ff481" whereas it should been like "test.cfm;jsessionid=2830a9edcf6f794ff481?CFID=1600&CFTOKEN=59663989". Since jsessionId is not correctly specified, server does not get this and hence creates a new session.

So how do you handle it? One way is to get the sessionId and urltoken from the session and create the url as expected (which is some effort on developer part). Alternatively, you can use a rather simple approach of using URLSessionFormat(url) which will do the exact thing which is required here. URLSessionFormat() appends the necessary information if cookies are disabled. If they are enabled, it does not do anything. Therefore it might be a better idea to always use this function for any GET or POST url.

The above code should actually have been


<cfset myurl=URLSessionFormat("test.cfm")>
<form method="post" action="#myurl#">
...
<input type="submit" value="Submit" >
</form>

10 comments:

Anonymous said...

Good to know about this technique - thanx! Might not want to assign to a variable called 'url' tho' since it is a scope...

Rupesh Kumar said...

Oh yes. thanks. edited.

Anonymous said...

hi rupesh...
this is exactly what I did in a project lately...
but I ran into a problem:
urlsessionformat() only rewrites the url if the client has cookies disabled... so most of the time your url would just look like "test.cfm"

This shouldn't be a problem, but I got informed that in some cases users got to see pages filled with other user's data.
Seems that these pages got cached by the company-proxy...
After appending the default #session.urltoken# everything worked just fine...
Did I miss to adjust something or what was it?!

greetings

Joerg Zimmer

Rupesh Kumar said...

Hi Joerg,
When cookies are enabled, session is tracked using cookies and urltoken will not be used by the server in that case.
It seems to me that it was a badly configured proxy. A proxy should never cache dynamic content and should only cache the static pages like html and images.
Was it a proxy in your company and faced by intranet users? or some external customers reported it to you?

Rupesh.

Anonymous said...

Hi Rupesh...
sorry for responding so late...
The site is faced to external users and the proxy is located somewhere on client-side...

I discovered something new...
We currently run a site in a subframe of our customers website... Because our site runs under a differnt domain, IE security settings forbid cookies from our site.
So we have a similar scenario here... This site runs on our CFMX 7.0.2 Cluster with 2 Nodes and a load-balancer in front of the webservers...
While usere where klicking around in our site, it seemed that with every click there was a new session generated for the user.
Even urlsessionformat did not resolve this...
Our Cluster ran with sticky sessions and session-replication turned off. I thought that the connector would handle the sticky-sessions and always use the same cfmx node for one session. But obviously it didn't - turning on session-replication solved this problem...

Are the connectors on the 2 webservers unable to interchange sticky-session data? maybe the load-balancer in front of the cluster should have user-persistent routing turned on...
Did I put this clear? Better an example :)

user requests page
load balancer routes him to server1
connector on server1 routes him to server1
session is created on server1

user requests next page
load balancer routes him to server2
connector on server2 routes him to server2
new session is created on server2 because sessionid is unknown

user requests next page
load balancer routes him to server1
connector on server1 routes him to server1
new session is created on server1 because sessionid is unknown again.

Rupesh Kumar said...

Hi Joerg,
What kind of load balancer are you using? Is it a hardware loadbalancer or software loadbalancer?
As I understand, you have a cluster of two cf nodes each of them behind a webserver using a connector. So actually you have two webservers with a load balancer in front. Is that correct?
If it is, then please check if the loadbalancer supports the sticky session concept. If it does then I think it might be a better idea to enable that.
Are both the connectors aware of both the cluster nodes? Let me check with JRun guys here if that would work or if there are any issues there. I know for sure that when connector is used as a load balancer then it does route the request proeprly maintaining session stickiness.
Rupesh

Anonymous said...

Hi again :)

You're right. 2 Webservers with Coldfusion behind a Software Loadbalancer (ldirectord). The load balancer is able to handle sticky sessions.. but it's not turned on at the moment...

Both connectors have the cluster connected.. not a node.. this should be ok.

Joerg

Dawesi said...

Nice one bro. Thanks for the heads up!

Anonymous said...

Nice to read all of ur discussion..
I am also facing one Jsessionid problem while IT security testing.
telnet our site then
pass the parameters like that


POST /sonystyle/searchsonystyle.do HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Host: www.sonystyle.com.sg
Cookie: JSESSIONID="
Content-Length: 10

query=sony

if JSESSIONID value is "
then I am getting error.
how to handle this JSESSIONID ?

Anonymous said...

I am also experiencing problems with session variables in a clusted environment.

With my test code, cookies on for the cluster URL - all fine. Disable cookies - session lost.

Go to either instance directly (via port) with cookies disabled it is fine, ie session stays.

CFMX 702 Ent
Win 2003
J2ee vars - sticky on