SessionRotate solution for JEE Sessions
By Pete Freitag
Update: As of the Servlet 3.1 specification, there is now a new way to rotate a J2EE session identifier using java's servlet api:
newSessionId = getPageContext().getRequest().changeSessionId();
What follows is a way to do this that also works on older versions of ColdFusion or Lucee:
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 jeeSessionRotateOldSession
.
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.
SessionRotate solution for JEE Sessions was first published on March 28, 2014.
If you like reading about coldfusion, session, or j2ee then you might also like:
- SessionInvalidate for JEE Sessions
- Scope Injection in CFML
- J2EE Sessions in CF10 Uses Secure Cookies
- Session Loss and Session Fixation in ColdFusion
The Fixinator Code Security Scanner for ColdFusion & CFML is an easy to use security tool that every CF developer can use. It can also easily integrate into CI for automatic scanning on every commit.
Try Fixinator
CFBreak
The weekly newsletter for the CFML Community
Comments
App A and App B are both hosted on the same server with the same domain, in different folders. They have unique Application objects, as defined in app.cfc.
However, when implementing your code, above, on App B, users are now predictably being logged out of App A if they are using both systems (which is not uncommon in our setup).
I'm prepared to start tinkering with your code to see if I can get it to create a new session in App B when you hit the index.cfm page WITHOUT invalidating the previous session. However, before I do, I figured it was worth shooting a message on this ancient post. :)
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.
--
Adam