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.
Archived Comments
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.
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>
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
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.
@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...
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.
@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.
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.
@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).
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
@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")
eh, I get it... Thanks
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?
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.)
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>
Can you show us more of the App.cfc file? Please use a code pasting service like pastebin.
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?
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.
Good point. Note to you forgot s in front of sessionid. :)
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. :-)
I trust in people's ability to read the whole thread. ;)
Corrected.
Awesome. Thanks for that. I'm sure it will help some folks finding this in the future.
Nice post and comments, all. Thanks! It's always heartening to read discussions that are sensible and constructive.