This wasn't quite an Ask Ben question, but it was a question that was asked of me and I would like to have a definitive place to point people when the question comes up again. A user asked me how to get ColdFusion to end the user's session when the user closes their browser. I have discussed ending sessions before, but let's just quickly hammer out a few points: you cannot force a session to end because a session is not something that is running (in the way that you think of a Windows application as running). These are all just chunks of memory space that get associated with different users. The best we can do is prevent a users' browser from re-associating with a given session on page refresh or page load. This will get the user to create a NEW session, but won't technically end the old session.
That being said, in order to get the user to create a new session when they re-open their browser (which can be thought of as ending their old session when the browser closes), we have to create session-only cookies. A session-only cookie is a cookie that is stored in the browser's memory but is never actually written to the user's hard drive. Therefore, when the browser closes and the memory space is flushed, the session-cookies disappear with it.
Creating a session-only cookie is rather easy. All we have to do is use ColdFusion's CFCookie tag to set the cookie values and exclude the "expires" attribute. The only problem we run into is that ColdFusion automatically sets the user's cookies when the session first runs. To prevent this from happening, we have to turn off client cookies as part of the application setting. Here is an Application.cfc component that demonstrates these two steps:
Launch code in new window » Download code as text file »
Notice that in the application settings, we are turning off the client cookies; but then, as soon as ColdFusion triggers the OnSessionStart() application event, we are using the SESSION's CFID and CFTOKEN values to manually create the session-only cookies. This will allow the browser to "hand shake" with the user's existing session because while the browser is running, it uses session-only cookies and hard-drive-persisted cookies in the same manner. That's all there is to it. This will ensure that when the user closes and re-opens their browser, they will get a new ColdFusion session.
If you want to test to make sure this works, you can use this simple page:
Launch code in new window » Download code as text file »
Here, I am just outputting the current date and the date the session was initialized. If the session was just created (new session), then both those time stamps should be the same.
Download Code Snippet ZIP File
Comments (11) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
REMatchGroup() UDF To Return Only Specified Group In RegEx Pattern
Ask Ben: Delete Values In A Given List Using ColdFusion
You can also do this by enabling J2EE session variables in CF Admin.
Posted by Scott Stroz on Jan 29, 2008 at 8:50 AM
@Scott,
I have never used J2EE session variables. Does that force a session-only cookie by default? Or is something more complicated going on behind the scenes?
Posted by Ben Nadel on Jan 29, 2008 at 8:55 AM
@Ben - I am not really sure of the mechanism. However, I should note that the keys in the session scope are different when J2EE session variables are enabled. If you have apps that look for stuff like CFID, sessionID, etc, they could break if you enable J2EE session variables.
Posted by Scott Stroz on Jan 29, 2008 at 9:11 AM
@Scott,
Sounds good. I remember having to learn something about it when I was studying for certification, but as I never use it, it has slipped away. I vaguely remember it having a dashed format that made me think of UUIDs, but not quite that big.
Posted by Ben Nadel on Jan 29, 2008 at 9:22 AM
Thanks for the insightful post as always Ben. I went through this on a contract where the client required that all cookies be session-only and the solution was to turn on J2EE Session Management.
Gary Gilbert has a really nice post on this:
http://www.garyrgilbert.com/blog/index.cfm/2007/11/12/Session-Cookies
Posted by Daniel Shaw on Jan 29, 2008 at 9:58 AM
Yeah I can agree that J2EE is the way to go, I was poiinted in this direction a fair while back and made the switch over. I think the origional conversation I was having was with regards to session hijacking and that how using J2EE will effectivly help secure down the session against hijacking more effectivly as once the browser has been closed the session is unobtainable again, quite whether this is true or not I dont know.
One thing worth baring in mind, this only works when the entire browser is closed, you'll generaly find that with tabbed browing, closing the single tab alone is not enough to 'kill' the session.
Cheers Ben,
Rob
Posted by Robert Rawlins on Jan 29, 2008 at 10:27 AM
@Robert - I believe we had that conversation in IRC.
It is also worth noting that when you close the browser, the session is not killed. The session will still last as long as the timeout will allow. Rather, when the browser is opened again, a NEW session is started.
Posted by Scott Stroz on Jan 29, 2008 at 10:31 AM
Thanks for clarifying that Scott,
I thought that would be the case, I was a little unsure as to the actual case so put my kill in inverted commas.
Cheers Mate,
Rob
Posted by Robert Rawlins on Jan 29, 2008 at 10:39 AM
@Robert,
Good call on the tabbed browsing. I know that I use tabbed browsing all the time. I assume this tabbed browsing issue affects both the standard cookie usage as well as the JSessionID stuff.
@Daniel,
Thanks for pointing out Gary's blog post. For some reason, I didn't see that before. Good stuff and good explanation of the benefits of JSessionsID.
Posted by Ben Nadel on Jan 29, 2008 at 10:58 AM
Given that some users close their browser RATHER than "logging off", I don't suppose there's a way for me to determine when they've closed their browser and killed their session cookie. If I wanted to run a cleanup function onSessionEnd (to store final user state or update stats), it will still wait for the session timeout to occur. Does that sound right?
Posted by Dan Sorensen on Jan 29, 2008 at 1:18 PM
@ Dan - You're quite right, onSessionEnd() will still run, but not untill the users session times out, as Scott talks about above, the session isnt actualy killed when the browser is closed, just a new one started when the browser is reopened.
Hope that helps mate,
Rob
Posted by Robert Rawlins on Jan 29, 2008 at 1:29 PM