Pete Freitag Pete Freitag

SessionRotate solution for JEE Sessions

Updated on December 11, 2023
By Pete Freitag
coldfusion

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.



coldfusion session j2ee

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:

Fixinator

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

This article helped me Pete, so thanks.

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
by Adam Cameron on 05/07/2015 at 8:10:23 AM UTC
@Adam - Good points, I agree with you that is should be up to the application to decide if it is ok to rotate the entire session. I suppose there may be some sandbox type concerns as to if it is really ok to allow an application to do something to another application. Perhaps it would make sense to have an argument to "force" rotation on JEE sessions, if not just allowing it to work.
by Pete Freitag on 05/28/2015 at 8:22:39 PM UTC
@Jan - good question, that is not something I have tested, but you could always wrap it in cflock if that turns out to be necessary.
by Pete Freitag on 05/28/2015 at 9:06:01 PM UTC
I was looking over your code example and one thing is not clear to me. Where I should call jeeSessionRotate() ?
by Milos on 03/07/2018 at 9:34:42 PM UTC
Pete, you mentioned that JEE sessions are shared over applications in the same domain. I just ran into this situation.

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. :)
by Kevin Krzyzanski on 02/21/2020 at 1:51:50 PM UTC