What is state? You may have heard the popular phrase, "The Web is a
stateless environment." Simply put, data cannot persist across
multiple page requests to the server. By nature, each request is
independent of the others.
When building Web applications,
we often have a need for
persistent data, data that is available
across multiple page requests
while being unique to each user.
There are many uses for persistent
data, from checking to see if a
user's session has timed out, to
storing information about a user
for use later in the application.
How Is State Created?
For data to persist, state must be created
between the client and the application.
In ColdFusion, state is created with two
identifiers/variables that are unique to
each user, CFID and CFTOKEN. For a
state to persist, these two variables must
be stored in one of two places: either in a
cookie on the client's browser, or passed
as variables in the URL with each page
request. ColdFusion then uses the CFID
and CFTOKEN to associate persistent
data with each user by associating the values
of these variables with CFID and
CFTOKEN variables that are set in the
client and session scopes. In ColdFusion,
creating state is a fairly simple process.
Although persistent data can be stored
in multiple places (in cookie, session, and
client variables), that is not the focus of
this article. Persistent variables will be
covered in Part 2. This article will address
the differences between using persistent
and non-persistent (session) cookies, and
how to maintain state when cookies aren't allowed or turned off.
Using Persistent Cookies for State
What is a "persistent cookie?"
A persistent cookie is written
to the client's hard drive as
opposed to being stored in the
client's memory. The cookie is
so named because it will
remain on the user's hard drive
(persist) either until its specified
expiration date or until it is
removed by the user.
The easiest and simplest way to create
state using persistent cookies is to use the
SETCLIENTCOOKIES attribute of the tag
<CFAPPLICATION> (see Listing 1). SETCLIENTCOOKIES
is an optional attribute
that defaults to "Yes" if not specified.
Upon execution, two variables, CFID and
CFTOKEN, are stored in a cookie on the
client's browser if the client has enabled cookies.
Two other attributes are also included
in <CFAPPLICATION>: CLIENTMANAGEMENT
and SESSIONMANAGEMENT.
These two attributes are optional for
<CFAPPLICATION>, but at least one
needs to be set to "Yes" in order for
ColdFusion to write the cookie storing
CFID and CFTOKEN to the client's browser.
Although you may never need to reference
these two variables, you can output
their values with #cookie.cfid# and #cookie.
cftoken# respectively. As stated above,
ColdFusion uses CFID and CFTOKEN
to associate persistent data with each unique user.
What is the advantage of using persistent
cookies if session variables time
out? The use of persistent cookies is
advantageous when using client variables.
Session variables typically time out after a
period of inactivity. However, client variables
can persist across multiple days,
weeks, and even months (this setting is
controlled in the ColdFusion
Administrator). By using persistent cookies,
client variables that were set weeks
ago can still be accessed by a previous
user. This could be a great way to store a
user's preferences.
Seems too easy, what's the catch?
Although creating state with persistent
cookies is very easy, it does have some
shortcomings. I'll give a scenario with
two users, Joe and Adam. Joe logs on to
an application at a public workstation.
Some information about Joe is pulled
from a database and stored in session
variables (i.e., credit card, SSN, phone
number, etc.). Joe does some work and
closes all browser windows when he finishes.
Adam comes along a few minutes later
and types in the URL for the same application,
but the auto fill from the browser's
history offers suggestions for other pages
in the same application. Adam then
selects one of the suggested URLs. Since it
was only a few minutes between Joe and
Adam, Joe's session hadn't expired and all
of Joe's information is now available to
Adam. Adam has the ability to navigate
the application as Joe. Whether intentional
or not, it could cause some serious damage.
Using persistent cookies in Web
applications may also be frowned upon
by some government agencies since
persistent cookies are written to the
client's hard drive. There may be
requirements to use nonpersistent cookies.
Using Nonpersistent (Session) Cookies
As opposed to their counterpart, nonpersistent cookies
are not written to the client's hard drive, but to the client's
memory. Once all instances/windows of a browser are
closed, then the nonpersistent cookie is erased from the
client's memory.
Nonpersistent cookies can be set using the CFCOOKIE tag
(see Listing 2). The key to creating a session cookie is to set the
EXPIRES attribute in <CFCOOKIE> to "Now". EXPIRES is an
optional attribute and defaults to "Now" if it is not specified. By
specifying EXPIRES="Now", a cookie is written to the client's
memory. If the cookie you are setting is already a persistent
cookie on the client, setting EXPIRES="Now" removes the cookie
from the cookie.txt file, leaving the cookie set in the client's
memory. Setting session cookies can be created regardless of
the value of SETCLIENTCOOKIES (Yes or No) in <CFAPPLICATION>.
In the example in Listing 2, I used the client-scope counterparts
to set the cookie variables. You may use either the client- or
session-scope counterparts of CFID and CFTOKEN to set the
cookies, depending on if you have the CLIENTMANAGEMENT
and SESSIONMANAGEMENT attributes enabled in <CFAPPLICATION>.
If Cookies Are Disabled
It is not uncommon to find users who may have cookies disabled
for one reason or another. New to ColdFusion MX is a
function, URLSessionFormat(), that appends the client information
to the URL if the client has cookies disabled. If cookies are
enabled, then no information is appended to the URL (see Listing 3).
Unfortunately, for developers using previous versions of
ColdFusion, URLSessionFormat() is not an available function. If
CLIENTMANAGEMENT is enabled in <CFAPPLICATION> the
user may append the variable CLIENT.URLTOKEN to a link.
Likewise, if SESSIONMANAGEMENT is enabled in <CFAPPLICATION>,
the user may append SESSION.URLTOKEN to a link (see
Listing 4). URLTOKEN is a concatenation of the CFID and CFTOKEN.
Using either method to append the CFID and CFTOKEN to a
URL can become cumbersome since it has to be performed with
every single link and form posted within the application. The
one exception is that neither method is necessary when using
<CFLOCATION> when setting ADDTOKEN="Yes". By setting the
attribute ADDTOKEN="Yes", <CFLOCATION> will automatically
append the URLTOKEN to the URL.
Conclusion
There is a myriad of possibilities to consider when creating
state for an application. Although there is no wrong way to configure
state management, the best solution is the one that fits
your organization's or client's needs. |