structClear and Sessions - Still bad?

This post is more than 2 years old.

In yesterday's blog post about cflogout, sessions, and the back button, there was a passing discussion about the structClear function and sessions. Phillip Senn asked if it was safe to use it on the session scope. It seems like it should be as long as you remember that this will not end the session but simply clear the current values.

In the past, the warnings against structClear used to mention that clearing the session would also cause the "special" session variables: CFID, CFTOKEN, and SESSIONID, to be nuked. You can see that described here in this tech note: ColdFusion 4.5 and the StructClear(Session) Function

I was convinced that this wasn't the case in ColdFusion 6 and higher, but I whipped up a quick test to check first. I first wrote this code:

<cfif structKeyExists(url, "clear")> <cfset structClear(session)> </cfif> <cfparam name="session.hits" default="0"> <cfset session.hits++> <cfdump var="#session#">

This should increment a session variable named hits. If I add clear=1 to the URL it will clear the entire session. I ran this code a few times and confirmed it worked fine:

I then added clear=1 and got:

So it looks like the special variables are definitely cleared. However, the code had no problem setting hits back to 0 and then adding one to it. But get this - I reloaded without clear=1 in the URL and got:

Notice that urltoken is returned but not cfid, cftoken, or sessionid. Also notice that urltoken is right. It has the same cfid/cftoken values from before. So is my session screwed? It seems not. If I used cfid/cftoken/sessionid in my code though it would certainly fail (unless I parsed apart session.urltoken).

I guess the old advice of clearing just want you need, or putting all your custom stuff into a session struct (session.data) and structClearing that, still holds true.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Raymond Camden posted on 1/2/2009 at 8:05 PM

As just a quick note, I also did some testing with the Admin API, specifically getting the active session count and the session info itself.

<cfinvoke component="cfide.adminapi.administrator" method="login" adminPassword="admin">
<cfinvoke component="cfide.adminapi.servermonitoring" method="getActiveSessionCount" cfapplicationname="stest" returnVariable="sc">

<cfoutput>Total session count: #sc#<br/></cfoutput>

<cfinvoke component="cfide.adminapi.servermonitoring" cfapplicationname="stest" method="getActiveSessions" returnVariable="sessions">

<cfdump var="#sessions#">

I noticed that when I cleared, it had no impact on the session information returned (ie, time since last access, age, etc). So it looks like, under the covers, there is nothing wrong with structClear(session). If you don't use cfid/cftoken/sessionid in code itself then it should be safe.

Comment 2 by Scott P posted on 1/2/2009 at 10:40 PM

I use this instead, provides me a bit more control.

<cfset safeList = "sessionid,urltoken,cfid,cftoken">
<cfloop collection="#session#" item="i">
<cfif not ListFindNoCase(safelist,i)>
<cfset structDelete(session,i)>
</cfif>
</cfloop>

Comment 3 by Red posted on 1/3/2009 at 12:02 AM

I have similar code to Scott's, but I do experience some weird session/caching behavior - I hope I don't deviate too much from the subject.

Basically, I login as user A, logout, login as user B, then I click on user-related parts of the site, and I get User A info. When I refresh the page it displays the correct user. CFID/CFTOKEN don't change as one would expect, rather, it takes few logout/refresh for them to change. Also, I added some debugging code onRequestStart() and it doesn't show every time(especially when it flips to the previously logged in user).

By adding rand() to the end of each user-related link on the site I fixed the problem(well if you can call that a fix).

I've never experienced this before, and I am sure I had to go out my way to break this. I searched around, and I couldn't find anything similar to this problem. I wonder if anyone has seen this before?

Thanks

Comment 4 by DanaK posted on 1/3/2009 at 11:06 PM

We have off again and on again session problems with people dropping their cfid/cftoken all the time, or with what Red said. It won't happen for weeks then all of a sudden boom it happens 110 times a day for 2 weeks. Removing structClear() was one of the first things I did (to no avail!).

I think I've torn things apart 100x and never could figure it out. I notice IE 6.x has various builds that were pushed out that would wreak general havok with session id's dropping on page hits etc.

Comment 5 by Raymond Camden posted on 1/4/2009 at 7:51 AM

@Red: First, you should NOT expect CFID/CFTOKEN to change. Those values are unique to your browser and machine. They have ZERO to do with actual session data. So when you logged in as A, then logged out, and came back as B, you were still on the same machine, so you would have the same CFID/CFTOKEN values.

You note that when you refreshed a page it seemed to show the right data - that could just be the browser cache aain. So I'd use the suggestions from this entry: http://www.coldfusionjedi.c...

Comment 6 by Raymond Camden posted on 1/4/2009 at 7:52 AM

Another way to think of the CFID/CFTOKEN not changing this. You get a phone number, right, 555-1111. The number is associated to you, Red. Then you die (sorry!) and I move in to your home and get your phone number. It's the same number, but now the name associated with it is Ray.

Comment 7 by Elliott Sprehn posted on 1/4/2009 at 3:56 PM

@Red

CFID and CFToken are sent in cookies when the session is started and your browser stores them for as long as the Set-Cookie header told it to. CF will only send you a new CFID and CFToken if your session expires or your browser didn't send the cookies (they didn't exist, or they expired).

As Ray said, the issue you're describing, and the fix with a random number, is definitely a browser caching problem.

Comment 8 by Brian posted on 1/5/2009 at 10:49 PM

I'm being lazy, but does this also apply to jsessionid?

@DanaK: We've seen that behavior when the cluster, er um, cluster-bombed... A user would be coming in through the master IP, but for some inexplicable reason, the affinity to a node never stuck...Which resulted in a new cfid/token with about every couple of hits...happened with predictable regularity on form submissions. And this was browser agnostic.

Comment 9 by Raymond Camden posted on 1/5/2009 at 10:50 PM

@Brian: I did not run my test w/ j2ee sessions turned on. I'd imagine we would see the same (the particular value would go away, urltoken would still work right, and sessions would still be fine anyway).

Comment 10 by Red posted on 1/6/2009 at 4:29 AM

Ray, Elliott, thanks for the explanation.

Ray, How do I "die" :(, and take my phone number with me, gracefully?

Elliott, I can expire CFID/CFTOKEN cookies on logout?

If I use StructClear() and get rid of CFID/CFTOKEN, at which point will ColdFusion send a new pair of CFID/CFTOKEN?

I do understand that the issue I originally asked about is due to caching, and is NOT related to sessions.

Thx

Comment 11 by Raymond Camden posted on 1/6/2009 at 5:30 AM

@Red - I don't think you get it (or I don't get your comment). There is no need to delete cfid/cftoken. You want to remove YOUR data, not the markers CF uses to uniquely identify you. If on login you set session.loggedin=true, then on logout you simply remove that variable: structDelete(session, "loggedin")

Comment 12 by Red posted on 1/6/2009 at 7:12 AM

eh, I get it... Thanks

Comment 13 by Don posted on 1/9/2009 at 3:18 AM

So now comes my problem with this. I do <cfset structClear(session)> and get the error "Variable SESSION is undefined"

I've even tried
<script>
structClear(session);
</script>
and get the same error.
What am I doing wrong?

Comment 14 by Raymond Camden posted on 1/9/2009 at 11:38 PM

The only way you would get that error is if it was on a page w/o any application context. Ie, a request where Application.cfc or .cfm was run. (And of course, sessionmanagement has to be turned on for the app.)

Comment 15 by Don posted on 1/10/2009 at 12:19 AM

Well, none of that is true. It is actually in the application.cfc file and session management is turned on.

I've run into this everytime I've tried to do it. Really strange. Different servers too.

The one I'm doing now has this in the application.cfc file.
<cfif ISDEFINED("url.reset") and url.reset is "DOIT">
<cfset #structClear(session)#>
<cflocation url="index.cfm">
</cfif>

Comment 16 by Raymond Camden posted on 1/10/2009 at 7:04 PM

Can you show us more of the App.cfc file? Please use a code pasting service like pastebin.

Comment 17 by Henry Ho posted on 3/14/2009 at 2:53 AM

In the CF8's doc on StructClear():
http://livedocs.adobe.com/c...

"Do not call this function on a session variable. For more information, see TechNote 14143..."

which is,

ColdFusion 4.5 and the StructClear(Session) Function
http://www.adobe.com/go/tn_...

The last workaround looks interesting. Kill the app? Wouldn't all active Session's be killed?

Comment 18 by Charlie Arehart posted on 1/26/2012 at 10:41 PM

Hey guys, about the code above that Scott P offered as a workaround, watchout for a typo in his whitelist. He was saying to "keep" these vars:

essionid,urltoken,cfide,cftoken

that should be:

essionid,urltoken,cfid,cftoken

It's a frequent slip (our brains typing--or in this case no one else even seeing) CFID and CFIDE as the same. :-)

Indeed, Ray, I suspect some may never see my comment here. Might you want to just edit Scott's comment to correct this? Feel free to delete mine in this case. (Or maybe you'd want to keep it for some reason, with this comment, and another from you saying you changed it.) Your call.

Comment 19 by Raymond Camden posted on 1/27/2012 at 12:31 AM

Good point. Note to you forgot s in front of sessionid. :)

Comment 20 by Charlie Arehart posted on 1/27/2012 at 1:16 AM

Cool, thanks. (Just a copy/paste error on my missing the "s".)

Did you by any chance change the comment from Scott? If so, perhaps you have to refresh the blog, because it's still showing CFIDE. Or were you preferring not to update his comment, hoping instead people will read all the way to the bottom before trying to use it? I fear they would not. :-)

Comment 21 by Raymond Camden posted on 1/27/2012 at 1:19 AM

I trust in people's ability to read the whole thread. ;)

Comment 22 by Raymond Camden posted on 1/27/2012 at 4:25 AM

Corrected.

Comment 23 by Charlie Arehart posted on 1/27/2012 at 4:41 AM

Awesome. Thanks for that. I'm sure it will help some folks finding this in the future.

Comment 24 by Eric posted on 6/28/2012 at 12:05 AM

Nice post and comments, all. Thanks! It's always heartening to read discussions that are sensible and constructive.