Select Page

Dynamically Enabling / Disabling Session Management In Lucee CFML 5.3.8.201

Cyberdime
Published: May 21, 2022

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.

Check out the license.

Source: www.bennadel.com