SessionRotate solution for JEE Sessions
As you may know the new ColdFusion 10 function SessionRotate works great if you are using ColdFusion sessions (CFID, CFTOKEN), but it doesn't actually rotate the session id or invalidate the underlying J2EE session if you are using JEE sessions. This is documented and by design, because a single J2EE session can span multiple ColdFusion applications on the same domain.
You can still rotate your J2EE sessions, but keep in mind that if you have multiple CF applications on the same domain it will only keep info for the current session (you could probably modify the code to get that working).
<cffunction name="jeeSessionRotate" output="false" returntype="string"> <cfset var sessionScope = Duplicate(session)> <cfset var req = getPageContext().getRequest()> <cfset StructDelete(sessionScope, "sessionid")> <cfset StructDelete(sessionScope, "urltoken")> <!--- invalidate old session ---> <cfset req.getSession().invalidate()> <!--- create a new JEE session ---> <cfset local.newSession = req.getSession(true)> <!--- copy the old session scope into a temp key in the new session, handled in onSessionStart ---> <cfif NOT StructIsEmpty(sessionScope)> <cfset local.newSession.setAttribute("jeeSessionRotateOldSession", sessionScope)> </cfif> <cfreturn local.newSession.getId()> </cffunction>
In your code call the above function to rotate the J2EE session, it will then store the old session scope in the new J2EE session directly with the key
Then in the
onSessionStart function of your
Application.cfc add the following to bring the old session data back into the new CF session:
<cffunction name="onSessionStart"> <cfset session.startTime = now()> <cfset local.oldSession = getPageContext().getRequest().getSession().getAttribute("jeeSessionRotateOldSession")> <cfif NOT IsNull(local.oldSession) AND NOT structIsEmpty(local.oldSession)> <cfloop list="#StructKeyList(local.oldSession)#" index="local.key"> <cfif NOT StructKeyExists(session, local.key)> <cfset session[local.key] = local.oldSession[local.key]> </cfif> </cfloop> <cfset getPageContext().getRequest().getSession().removeAttribute("jeeSessionRotateOldSession")> </cfif> </cffunction>
This is needed because the CF session scope is no longer usable after you run
jeeSessionInvliadate(), so we need to wait until onSessionStart is invoked again with the new jee session to copy the old CF session scope back over.
Note: that the
jeeSessionRotate function above only copies values set via CF's session scope, it doesn't copy any values that other JEE applications might have set, it could be modified to do that if you needed to.
Like this? Follow me ↯Tweet Follow @pfreitag
You might also like:
- Scope Injection in CFML - March 3, 2015
- J2EE Sessions in CF10 Uses Secure Cookies - April 5, 2013
- Session Loss and Session Fixation in ColdFusion - March 1, 2013
- J2EE Session Cookies on ColdFusion / JRun - February 8, 2010
- Installing multiple versions of CFMX on JRun - February 8, 2005
Just on the "This is documented and by design, because a single J2EE session can span multiple ColdFusion applications on the same domain".
Should the "design" level here be the application, not CF? Whilst it *might* be the case that JEE sessions are spanned across multiple CF applications on the same domain, this is not essential nor vital to JEE-based session operations. Nor would I think it's actually the most common happenstance.
It should be down to the application to make judgement calls as to how / when session rotation is managed, not down to some engineer in the Adobe CF office, shouldn't it?
That aside, if sessionRotate() doesn't actually do what it says on the tin in these situations, it should raise an exception when used in a JEE-session-using environment, not simply "run" and not do anything?
Cheers for the insight though. Excellent stuff.