facebook google plus twitter
Webucator's Free ColdFusion MX Tutorial

Lesson: Session & Application Management

Welcome to our free ColdFusion MX tutorial. This tutorial is based on Webucator's Comprehensive ColdFusion Training course.

Lesson Goals

  • To understand the difference between ColdFusion session management and J2EE session management.
  • To use the <cfapplication> tag is used to set defaults for session state management.
  • To use Application variables.
  • To use session variables to remember that the users are logged in as they go from page to page.
  • To understand the basics of structures.
  • To use cookies to make it easier for users to log in on future visits.

Sessions

A session begins when a visiting client somehow identifies itself to the web server. The web server assigns the client a unique session id, which the client uses to re-identify itself as it moves from page to page on the website. Most of the time, these unique ids are stored in session cookies that expire after the client hasn't interacted with the server for some amount of time. The amount of time varies depending on the web application. For example, an online investment site might have very short sessions, so that if a user leaves her computer without logging out, another user who sits down at the same computer several minutes later cannot continue with the first user's session.

Configuring Sessions

The picture above shows the Memory Variables settings in ColdFusion Administrator, where Session management is configured.

J2EE Session Variables

The first checkbox gives the option of using J2EE session variables instead of ColdFusion session variables. The two major advantages of using J2EE session variables are:

  1. Sessions end when a user closes the browser. This is not the case with ColdFusion session variables.
  2. The Session scope is serializable, which allows session variables to be shared across servers. Again, this is not the case with ColdFusion session variables.

There is really no downside to using J2EE session variables, so it is recommended that you check this box.

Enabling Application Variables

The second checkbox gives the option to enable Application variables. Application variables are shared between all users of the application and live until ColdFusion Application Server is shut down, they are explicitly deleted, or the application times out due to a setting in <cfapplication>.

Application variables are useful for storing data such as data source names and file paths that are the same for all users over the life of the application, so it is recommended that you check this box.

Enabling Session Variables

The third checkbox gives the option to enable Session variables. Session variables are variables that are specific to a user's session (or visit) on the site. If session variables are not enabled, it becomes very difficult to track a user throughout his visit, so it is recommended that you check this box as well.

The <cfapplication> Tag

The <cfapplication> tag is used to:

  1. Define the name of a ColdFusion application.
  2. Enable or disable Client variables.
  3. Specify where Client variables are stored.
  4. Enable Session variables.
  5. Set Application variable timeouts.
<cfapplication> Attributes
Attribute Description
name Name of application.
loginStorage Where to store login variables (in Cookies or Session).
clientManagement Enable client variables. Default is "No".
clientStorage Where to store client variables.
setClientCookies Enable cookies. Default is "Yes".
sessionManagement Enable session management. Default is "No".
sessionTimeout Lifespan of session variables.
applicationTimeout Lifespan of application variables.
setDomainCookies Sets CFID and CFTOKEN for a domain.

The <cfapplication> tag is most often used at the top of the Application.cfm file. A typical <cfapplication> tag looks like this:

<cfapplication sessionmanagement="yes" clientmanagement="yes" name="RunnersHome">

If sessionTimeout and applicationTimeout are not defined in the <cfapplication> tag, as in the tag above, the default values set in ColdFusion Administrator are used.

Basics of Structures

A ColdFusion structure is a data type that can be used to hold collections of like data. ColdFusion provides many functions to make it easy to work with and manipulate structures. A few of these functions are described in the table below.

Structure Functions
Function Description
IsStruct Returns true if the specified variable is a structure.
StructNew Creates a new structure.
StructClear Removes all data from specified structure.
StructDelete Removes the specified item from the specified structure.
StructFind Returns the value associated with the specified key in the specified structure.

The example below creates a structure called person, adds properties to the structure, deletes a property and then loops through a substructure.

Code Sample:

SessionAndApplication/Demos/Structure.cfm
<html>
<head>
<title>Structure Demo</title>
</head>
<body>
<cfset person = StructNew()>
<cfset person.firstName = "Paul">
<cfset person.lastName = "McCartney">
<cfset person.age = 61>
<cfset person.talents.sing = True>
<cfset person.talents.playsGuitar = True>
<cfset person.talents.bungyJumps = False>

<cfset StructDelete(SESSION, "username")>


<cfoutput><p>Structure Elements: #StructCount(person)#</p></cfoutput>
<ul>
<cfloop collection="#person.talents#" item="talent">
	<cfoutput><li>#talent#: #person.talents[talent]#</li></cfoutput>
</cfloop>
</ul>
</body>
</html>

The Session, Application, and Client scopes are all available as ColdFusion structures, which means that they can be manipulated using the Structure functions.

Session Example

Code Sample:

SessionAndApplication/Demos/Session1.cfm
               <cfset SESSION.SessVar = "Hello world!">

<html>
<head>
<title>Session Page 1</title>
</head>
<body>
The content of SESSION.SessVar is <cfoutput>#SESSION.SessVar#</cfoutput>.

<a href="Session2.cfm">Next page</a> 
</body>
</html>

This page sets and outputs a session variable.

Code Sample:

SessionAndApplication/Demos/Session2.cfm
<html>
<head>
<title>Session Page 2</title>
</head>

<body>
The content of SESSION.SessVar is still <cfoutput>#SESSION.SessVar#</cfoutput>.
<cfset StructDelete(Session,"SessVar")>

<a href="Session3.cfm">Next page</a>
</body>
</html>

This page outputs the same session variable and then deletes it with StructDelete().

Code Sample:

SessionAndApplication/Demos/Session3.cfm
<html>
<head>
<title>Session Page 3</title>
</head>

<body>
The content of SESSION.SessVar is no longer <cfoutput>#SESSION.SessVar#</cfoutput>.

</body>
</html>

This page tries to read the deleted session variable and fails. It errors with a message like " Element SESSVAR is undefined in SESSION."

Creating an Application.cfm Page

Duration: 5 to 10 minutes.

In this exercise, you will create a simple Application.cfm page.

  1. Open a new page and save it as Application.cfm in the SessionAndApplication/Exercises folder.
  2. Use the <cfapplication> tag to:
    • Name of a application "RunnersHome".
    • Enable Client variables.
    • Enable Session variables.
  3. Write an if condition to check if an Application variable named datasource is defined. If it is not, set an Application variable called datasource with the value of runners.

Solution:

SessionAndApplication/Solutions/Application.cfm
<cfapplication sessionmanagement="yes" clientmanagement="yes" name="RunnersHome">

<cfif NOT isDefined("APPLICATION.datasource")>
	<cfset APPLICATION.datasource="runners">
</cfif>

Cookies

Cookies are small text files that sit on the client machine. Web pages with the right permissions can read from and write to cookies. They are generally used to track user information between visits.

In ColdFusion, cookies are set with the <cfcookie> tag, which takes several attributes.

<cfcookie> Attributes
Attribute Description
name The cookie's name (required).
value The cookie's value.
expires The cookie's expiration date (if this isn't set, the cookie will expire when the browser window is closed).
secure A flag indicating whether the cookie should only be read over https.
path The directory path on the server that can read the cookie.
domain The domain name that can read the cookie.

The following code will set a cookie that expires in one week.

<cfcookie name="firstname" value="Paul" expires="7">

The following code will set a cookie that expires in on December 31, 2008.

<cfcookie name="firstname" value="Paul" expires="12/31/08">

The following code will set a cookie that never expires.

<cfcookie name="firstname" value="Paul" expires="never">

To delete a cookie, set the expiration date to now(), like this.

<cfcookie name="firstname" value="Paul" expires="now">

Authentication with Session Control

Duration: 45 to 60 minutes.

In this exercise, you will create a login form that allows a user to log in to a site, rather than just a page on the site. You will also modify several other pages so that their content changes based on whether or not the user is logged in.

  1. Open SessionAndApplication/Exercises/Login.cfm.
  2. If the user logs in successfully, set session variables for firstname, lastname, and userid with values from the query. Then redirect to index.cfm.
  3. In the user's log in fails, set a variable called badlogin to true.
  4. Open SessionAndApplication/Exercises/index.cfm.
  5. Write code that
    • Sets the firstname session variable with the value of "Stranger" if it doesn't already exist.
    • Changes the sentence that indicates the time and date to include the user's first name (e.g, "John the time is...").
    • Replaces the login form with "Logged in as firstname lastname" if the user is logged in.
  6. Open SessionAndApplication/Exercises/Logout.cfm.
    • Write code to log the user out. You'll need to use StructDelete().
  7. Open SessionAndApplication/Exercises/Includes/Navbar.cfm.
    • Change the code so that the last link is to Logout.cfm if the user is logged in and to Login.cfm if she is not.
    • If the user is logged in, add an additional link to MyAccount.cfm, which has been created for you.
  8. Open SessionAndApplication/Exercises/Register.cfm.
    • Modify it to automatically log the user in on a successful registration.
  9. When you have completed your work, test the site:
    • Go to SessionAndApplication/Exercises/Register.cfm and create a new account.
    • Click on the link to the home page. You should be logged in.
    • Click on the Logout link. You should be logged out.
    • Click on the Login link and login.

Write code so that the user can indicate that she would like to be remembered between visits. If she chooses to be remembered, she should never have to login again. You will have to modify Login.cfm, Application.cfm and Logout.cfm.

Solution:

SessionAndApplication/Solutions/Login.cfm
<cfif isDefined("FORM.submitted")>
	<cfquery name="logincheck" datasource="#APPLICATION.datasource#">
		SELECT firstname, lastname, userid
		FROM Users
		WHERE email='#FORM.email#'
			AND password='#FORM.password#'
	</cfquery>
	<cfif logincheck.RecordCount EQ 1>
		<cfset SESSION.firstname = logincheck.firstname>
		<cfset SESSION.lastname = logincheck.lastname>
		<cfset SESSION.userid = logincheck.userid>
		<cflocation url="index.cfm" addtoken="no">
	<cfelse>
		<cfset badlogin=true>
	</cfif>
</cfif>
---- C O D E   O M I T T E D ----

Solution:

SessionAndApplication/Solutions/index.cfm
               <cfparam name="SESSION.firstname" default="Stranger">

<html>
<head>
<title>Runners Home&trade;</title>
<link href="Styles/Main.css" rel="stylesheet">
</head>
<body>
<cfinclude template="Includes/NavBar.cfm">

<div id="greeting">
	<cfoutput>#SESSION.firstname#, the time is #TimeFormat(Now(),"h:mm tt")# on #DateFormat(Now(), "mmmm d, yyyy")#.</cfoutput>
</div>

<table align="center" cellpadding="10" cellspacing="0"
					width="100%" height="100%" id="hometable">
<tr valign="top">
<td width="25%" id="leftcolumn">
	<cfif isDefined("SESSION.userid")>
		Logged in as <cfoutput>#SESSION.firstname# #SESSION.lastname#</cfoutput>
	<cfelse>
	<h2>Log in</h2>
	<form method="post" action="Login.cfm">
	<input type="hidden" name="submitted" value="true">
		<table>
		<tr>
			<td class="whiteText">Email:</td>
			<td><input type="text" name="email" size="14"></td>
		</tr>
		<tr>
			<td class="whiteText">Password:</td>
			<td>
			<input type="password" name="password" size="14">
			</td>
		</tr>
		<tr>
			<td align="right" colspan="2">
			<input type="submit" value="Log in">
			</td>
		</tr>
		</table>
	</form>
	<a href="Register.cfm">Register</a>
	</cfif>
---- C O D E   O M I T T E D ----

Solution:

SessionAndApplication/Solutions/Logout.cfm
               <cfset StructDelete(Session,"userid")>
<cfset StructDelete(Session,"firstname")>
<cfset StructDelete(Session,"lastname")>

<cflocation url="index.cfm" addtoken="no">

Solution:

SessionAndApplication/Solutions/Includes/NavBar.cfm
<div align="center" id="navbar">
	<a href="index.cfm">Home</a> |
	<a href="Races.cfm">Races</a> |
	<a href="Resources.cfm">Resources</a> |
	<a href="Calculator.cfm">Calculator</a> |
	<a href="RunningLog.cfm">Running Log</a> |
	<cfif isDefined("SESSION.userid")>
		<a href="MyAccount.cfm">My Account</a> |
		<a href="Logout.cfm">Log out</a>
	<cfelse>
		<a href="Login.cfm">Log in</a>
	</cfif>
</div>

Solution:

SessionAndApplication/Solutions/Register.cfm
---- C O D E   O M I T T E D ----
	<cfif Form.password EQ Form.password2>
		<cfquery datasource="#Application.datasource#" name="insert">
			INSERT INTO Users
			(firstname, lastname, email, password)
			VALUES ('#Form.firstname#', '#Form.lastname#', '#Form.email#', '#Form.password#')
		</cfquery>
		<cfquery datasource="#Application.datasource#" name="getuserid">
			SELECT userid
			FROM Users
			WHERE email='#FORM.email#'
		</cfquery>
		<cfset Session.firstname = Form.firstname>
		<cfset Session.lastname = Form.lastname>
		<cfset Session.userid = getuserid.userid>
		
		<cflocation url="index.cfm" addtoken="no">

	<cfelse>
		<p class="errors"><b>Your passwords
		do not match. Please <a href=
		"Register.cfm">try again</a>.</p>
	</cfif>
---- C O D E   O M I T T E D ----

Challenge Solution:

SessionAndApplication/Solutions/Login-challenge.cfm
<cfif isDefined("FORM.submitted")>
	<cfquery name="logincheck" datasource="#APPLICATION.datasource#">
		SELECT * FROM Users
		WHERE email='#FORM.email#'
				AND password='#FORM.password#'
	</cfquery>
	<cfif logincheck.RecordCount EQ 1>
		<cfset SESSION.firstname = logincheck.firstname>
		<cfset SESSION.lastname = logincheck.lastname>
		<cfset SESSION.userid = logincheck.userid>
		<cfif isDefined("FORM.rememberme")>
			<cfcookie name="loggedin" value="#logincheck.userid#" expires="never">
		</cfif>
		<cflocation url="index.cfm" addtoken="no">
	<cfelse>
		<cfset badlogin=true>
	</cfif>
</cfif>
<cfparam name="FORM.email" default="">
<html>
<head>
<title>Login Page</title>
<link href="Styles/Main.css" rel="stylesheet">
</head>
<body>
<cfinclude template="Includes/NavBar.cfm">

<div id="subbody" align="center">

	<h2>Log in</h2>
	<cfif isDefined("badlogin")>
		<p class="errors"><b>That is not the
			correct email and password. Please
			<a href="Login-challenge.cfm">try again</a>.</p>
	</cfif>
	<cfoutput><form method="post" action="#CGI.SCRIPT_NAME#"></cfoutput>
	<input type="hidden" name="submitted" value="true">
		<table>
		<tr>
			<td>Email:</td>
			<td><input type="text" name="email"
					value="<cfoutput>#FORM.email#</cfoutput>" size="40"></td>
		</tr>
		<tr>
			<td>Password:</td>
			<td>
			<input type="password" name="password" size="14">
			</td>
		</tr>
		<tr>
			<td colspan="2">
			<input type="checkbox" name="rememberme"> Remember Me
			</td>
		</tr>
		<tr>
			<td align="right" colspan="2">
			<input type="submit" value="Log in">
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<br><a href="Register.cfm">Register</a>
			</td>
		</tr>
		</table>
	</form>
</div>
<cfinclude template="Includes/Footer.cfm">

</body>
</html>

Challenge Solution:

SessionAndApplication/Solutions/Application-challenge.cfm
<cfapplication sessionmanagement="yes" clientmanagement="yes" name="RunnersHome">

<cfif NOT isDefined("APPLICATION.datasource")>
	<cfset APPLICATION.datasource="runners">
</cfif>

<cfif NOT isDefined("SESSION.userid") AND isDefined("COOKIE.loggedin")>
	<cfquery name="getuserinfo" datasource="#APPLICATION.datasource#">
		SELECT firstname,lastname,userid
		FROM Users
		WHERE userid=#COOKIE.loggedin#
	</cfquery>
	<cfif getuserinfo.RecordCount EQ 1>
		<cfset SESSION.firstname = getuserinfo.firstname>
		<cfset SESSION.lastname = getuserinfo.lastname>
		<cfset SESSION.userid = getuserinfo.userid>
	</cfif>
</cfif>

Challenge Solution:

SessionAndApplication/Solutions/Logout-challenge.cfm
<cfset StructDelete(Session,"userid")>
<cfset StructDelete(Session,"firstname")>
<cfset StructDelete(Session,"lastname")>

<cfcookie name="loggedin" expires="now">

<cflocation url="index.cfm" addtoken="no">