Skip to main content
Ben Nadel at cf.Objective() 2017 (Washington, D.C.) with: Brad Wood
Ben Nadel at cf.Objective() 2017 (Washington, D.C.) with: Brad Wood@bdw429s )

Dynamically Enabling / Disabling Session Management In Lucee CFML 5.3.8.201

By on
Tags:

Currently, my blog is composed of two completely separate ColdFusion applications: one for the public facing functionality (you) and one for the content publisher (me). The public facing ColdFusion application has no session management. But the internal facing ColdFusion application has sessions and login-based authentication. As I've been refactoring this platform, I briefly considered combining the two ColdFusion applications and just dynamically enabling sessions for my user. I dismissed this approach as unnecessarily complicated; but, the fact that it's even possible is a fascinating aspect of ColdFusion. As such, I thought that I might quickly demonstrate that you can dynamically enable and disable session management in Lucee CFML 5.3.8.201.

A not-obvious behavior of the ColdFusion application framework is that your Application.cfc component gets instantiated on every single request that runs through your application. Essentially, there are these detached "application" and "session" memory spaces / scopes (ie, persistent state); and, part of the job that your Application.cfc component performs is to "attach" this state to the current request.

Because of this per-request instantiation, the Application.cfc component gives us an opportunity to dynamically change the settings on every single request. This is not necessarily a "Good Thing"โ„ข since much of the application's configuration should be static (think data sources, think SMTP servers, think path mappings, etc.). But, that doesn't mean we can't get a little jiggy with it from time to time.

In a ColdFusion application, session management is determined by the following Application.cfc property:

this.sessionManagement = true

This is defined in the component's pseudo-constructor: the space inside the CFComponent tag but outside of any CFFunction tags. To be pedantic, a ColdFusion component's pseudo-constructor is run whenever a ColdFusion component is instantiated. So, if our Application.cfc is instantiated on every incoming request, the pseudo-constructor is also run on every single request.

Which means, we have programmatic control over the this.sessionManagement setting on every single request.

To demonstrate this, let's create an Application.cfc ColdFusion component that changes the this.sessionManagement value based on the existence of a Cookie scope property:

cookie.enableSession

To be clear, this is not a special cookie. It's completely arbitrary. We could have named it, cookie.iCanHazSessions. It's just a dynamic "flag" that gives us something to hook into on each request.

With that said, here's our demo Application.cfc:

component
	output = false
	hint = "I define the application settings and event-handlers."
	{

	// Define the core settings.
	this.name = "ConditionalSessionTest";
	this.applicationTimeout = createTimeSpan( 1, 0, 0, 0 );

	// In this demo, we're dynamically attaching / detaching the SESSION SCOPE to the
	// current request. This is based on the existence of a "flag" cookie. One of the most
	// fascinating things about ColdFusion is that basically all of the settings can be
	// adjusted on a PER-REQUEST basis; including session management.
	if ( cookie.keyExists( "enableSession" ) ) {

		this.sessionManagement = true;
		this.setClientCookies = true;
		this.sessionTimeout = createTimeSpan( 0, 0, 10, 0 );

	} else {

		this.sessionManagement = false;
		this.setClientCookies = false;

	}

	// ---
	// PUBLIC METHODS.
	// ---

	/**
	* I get called once to initialize the session associated with the request.
	*/
	public void function onSessionStart() {

		session.requestCount = 0;

	}


	/**
	* I get called once to initialize the request.
	*/
	public void function onRequestStart() {

		// If the SESSION is not enabled for the current request, the SESSION SCOPE is
		// undefined. As such, we would have to take care to test for its existence before
		// we reference it.
		request.isSessionEnabled = isDefined( "session" );

		if ( request.isSessionEnabled ) {

			session.requestCount++;

		}

	}

}

As you can see, in the Application.cfc's pseudo-constructor, we're dynamically setting the session management configuration based on the existence of the enableSession cookie. If session management is not enabled in ColdFusion, the session scope is undefined. As such, in order to make it easier to interact with our transient session management, we're setting a request.isSessionEnabled property.

For this demo, the session scope holds nothing more than a simple hit-counter, which we increment on each onRequestStart() event-handler.

Now, to bring this demo together, let's create an index page that allows us to toggle session manage on/off for the current request. We're going to do this by either setting the enableSession cookie or deleting it.

<cfscript>

	// Default our URL parameters for easier consumption.
	param name="url.startSession" type="boolean" default=false;
	param name="url.stopSession" type="boolean" default=false;

	// In this demo, we're dynamically enabling / disabling the ColdFusion Session based
	// on the presence of a Cookie. As such, if we want to bind the session to the current
	// request, we have to set the flag cookie (session will be attached on NEXT request).
	if ( url.startSession ) {

		cookie.enableSession = true;

	// ... and, if we don't want to bind the session to the current request, we have to
	// delete the cookie (session will be detached on NEXT request).
	} else if ( url.stopSession ) {

		cookie.delete( "enableSession" );

	}

	// If we're changing the session settings in either direction, let's refresh the page
	// to apply the new cookie-based settings for the demo (just so we can immediately
	// see the differences in the rendering down below).
	if ( url.startSession || url.stopSession ) {

		location( url = cgi.script_name, addToken = false );

	}

</cfscript>
<cfoutput>

	<h1>
		Conditional ColdFusion Session Testing
	</h1>

	<p>
		Sessions enabled:
		#yesNoFormat( getApplicationMetadata().sessionManagement )#
	</p>

	<cfif request.isSessionEnabled>
		<p>
			<strong>Hit count:</strong> #session.requestCount#
		</p>
	</cfif>

	<p>
		<a href="#cgi.script_name#?startSession=true">Start session</a> ,
		<a href="#cgi.script_name#?stopSession=true">Stop session</a> ,
		<a href="#cgi.script_name#?_=#createUniqueID()#">Refresh</a>
	</p>

</cfoutput>

As you can see, this page outputs the ColdFusion application's session management state by inspecting the getApplicationMetadata() result. Then, if session management is enabled, we're outputting the current session's "hit count".

Now, if we run this ColdFusion application in an incognito window in Chrome, and toggle session management on and off, we get the following output:

Refreshing the page shows conditionally applied session management in ColdFusion.

As you can see, some of the requests interacted with the current session; and, some of the requests did not. This was based on the existing of the enableSession cookie, which - in turn - determined if the this.sessionManagement flag was turned on in the Application.cfc ColdFusion framework component.

ColdFusion is pretty crazy, right?! I think it's way more dynamic than many people even realize.

Why Not Just Enable Sessions All the Time?

Now, this is just a demo to showcase the dynamic nature of the ColdFusion request model. But, you may wonder why I wouldn't just enable sessions all the time and not have to think about it? Memory: every ColdFusion session that gets enabled has space allocated for it in the server's RAM (or whatever session storage system you've configured). And, each session is bound to a request using cookies. So, if a Search engine (for example), makes tens of thousands of request to your application a day, but doesn't send over cookies - that's tens of thousands of sessions being allocated and never used.

Is this a problem on modern server architecture where storage and RAM are relatively cheap? Maybe not. But, it's still worth considering the trade-offs.

Again, I'm not actually going to use this approach since I think it adds unnecessary complexity - I'm just going to keep my public / private ColdFusion applications separate for now. But, it made fertile ground for an exploration of the highly dynamic ColdFusion application framework.

Want to use code from this post? Check out the license.

Reader Comments

14 Comments

I do something similar, to extend session timeouts. I use Commandbox locally for development, and I hate having to login when I pick back up tomorrow, or later today, in my coding efforts.

If my domain name has the "local" in it, or it detects my local subnet IP range... I get five days! (The double entry of the IP is me being lazy and not counting the characters.) And bufferOutput just lets me dump/abort anywhere and actually SEE it.

this.sessionTimeout    = createTimespan( 0, 0, 30, 0 );
if( cgi.host == "localtools.mysite.com" || left(cgi.host, len("192.168.60")) == "192.168.60") {
	// Enable us to dump and abort anywhere
	this.bufferOutput=true;
	this.sessionTimeout    = createTimespan( 5, 0, 0, 0 );	// Five days
}
15,329 Comments

@Will,

1000% yes on hating to have to keep logging in locally! I really like this idea - I'm going to steal it for sure ๐Ÿ™ƒ I'm going to have to look up bufferOutput, I haven't used that setting before. Based on what you're saying, I'm guessing it has to do with what happens inside of non-output areas of the code like component and cfscript.

18 Comments

Yeah it is a very handy feature of CFML!

I've used it to either set the session timeout to 1 second (or disable sessions) when a bot hits requests your site - that way it doesn't consume the heap/ram and often bots will send new requests without cookies, causing a new session to be created on every request.

15,329 Comments

@Pete,

I think I used to do something similar. But, I've long-since stopped using sessions on the blog and just use a few Cookies. Of course, that was before GDPR laws. So, probably time to re-think something; or, at least figure out which cookies are allowed under GDPR.

3 Comments

@Ben,

Its interesting that the session still exists even though its disabled. What would happen if you dump the session scope without it being enabled?

We use the same technique that @Pete uses to disable sessions if its a bot. That has really helped us keep the memory down on apps that use sessions.

Tim

15,329 Comments

@Tim,

Hmm, I can't remember off the top of my head what happens. I think (90% sure) you get an error saying that the session scope isn't defined. But yeah, either this way or Pete's way, and it's really helpful to manage bloated memory usage ๐Ÿ’ช

Post A Comment — I'd Love To Hear From You!

Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.