1 person found this helpful
OK, there are three things to consider here, all of which are separate - interrelated - concepts
A session is a representation (for lack of a better word) on the ColdFusion server which reflects a current visitor to the site. Because the CF server and the client browser don't communicate with each other directly, the CF server relies on the CFID/CFTOKEN (or JSESSIONID) cookies to be passed from client to web server to CF server. Then CF can associate its session to the client's session.
As part of the above session, a session scope is availed to CFML code. The session scope is not "the session", it is something that exists as a result of a session existing. Once a session expires, the session scope for that session will be cleaned up too.
Session even handlers
When a session starts, one of the things it does it raise an "session start" event, which the CF application framework will listen for, and if an onSessionStart() handler is present, it'll run said event handler. This does not start the session, it runs as a side-effect of the session starting.
Similarly there is a session end event, and an onSessionEnd() handler.
Now... clearing the session scope does not expire a session. Running onSessionEnd() doesn't end the session any more than running onSessionStart() starts a session. Think of it in terms of mouse events: running the onClick() event handler manually does not cause the physical mouse button to depress, does it? No. Same with CF application framework event handler functions. Just because the framework runs those event handlers when events occur does not mean manually running those handlers causes the events to occur.
Also clearing the session cookies will likewise not end a session, all it will do is kill the association between the browser and an existing CF session on the server. On the next request the CF server will not find the cookies, go "ooh... new session..." and start a new session, and send new cookies to the browser. However as its lost its association between the browser and the previous session, it doesn't have any way of knowing that it should end that previous session. So that session will linger until the session time out occurs, at which point CF will terminate the session, raise the "session end" event, and the application framework will run the "onSessionEnd()" event handler if one is present.
If you want to actually kill a session, you will need to run sessionRotate() (or possibly sessionInvalidate() might work). I've never used these so don't know if they kill the previous session, or simply give the client a new set of cookies. These functions are new to CF10. If you have an earlier version, you're gonna have to mess with the SessionTracker (which you can google).
Thanks for this detailed explanation. I understood.
Could you please help me what all the steps should I taken for care while implementing a login and logout system in Coldfusion.
So, during log out of my application I need to do following things.
1]Clear the session scoped business logic identifiers(variables)
2]Expire the cookies -CFID/CFTOKEN
If we are doing all these it will start a new session scope with new CFID/CFTOKEN values.
Do you agree with this or will there be any problem if these cookies got expired.?
Do not see a LOGIN SYSTEM and SESSION MANAGEMENT as two same things; they are different.
In short, the CFID/CFTOKEN cookies are used to ensure that a visitor's requests to your site ensure they have access to the proper SESSION values. This is SESSION MANAGEMENT between the client browser and server.
A LOGIN SYSTEM is used to authenticate a user (usually by credentials such as username and password). Many will create a SESSION variable such as 'isLoggedIn' which can be read by application logic to determine if a user is "logged in".
In short, just because a SESSION exists, does not mean a user is LOGGED IN.
Because of that, cutting the ties between the session and user by killing the CFID/CFTOKEN cookies is not a good idea. This just makes it so that on the user's next request, another session is created for no good reason.
Instead, just have a SESSION scope variable become updated so that 'isLoggedIn' is set to false when the user logs out. Your logic could use a param to check the user's login status:
<cfparam name="SESSION.isLoggedIn" default="false" />
<cfif not SESSION.isLoggedIn>
<!--- User is not logged in. --->
In short, when logging a user OUT, don't mess with the session, it has nothing to do with login status. Simply update a variable to reflect the user's login status.
User visits page > CF Creates Session A to store session variables, it sends back a CFID/CFTOKEN cookie that correlates to SESSION A.
User 'logs in' to page > Code updates a SESSION A variable 'isLoggedIn' to 'true'.
User goes to restricted area > Code checks the SESSION scope, sees the isLoggedIn is set to true and allows access.
User 'logs out' of page > Delete CFID/CFTOKEN cookies, SESSION A is now orphaned and continues living, wasting space for Session Timeout Duration
User visits another page > CF sees no CFID/CFTOKEN cookies, so creates SESSION B and sends back CFID/CFTOKEN associated with it.
See, in the aforementioned, killing the cookies merely wastes server resources by creating a new session. Instead, have your logic on Step 4 just set 'isLoggedIn' to false. That way SESSION A stays "alive" even though the user is now "logged out" of the page. No need to create a new session.
Thanks for this illustration. But still one doubt in my mind.
Suppose , For session A value of CFID/CFTOKEN is 100/200
I waited for some time to timeout the session (I put timeout period as 10mnts) , then I checked the CFID/CFTOKEN values but it still same (100/200).
So just to add to my knowledge that is if a new session is starting after the session got expired after a particular timeout period it doesnt mean a new CFID/CFTOKEN value will be generated.right??... because a new session is starting after the session time out.
If Session A's CFID/CFTOKEN cookies are on your machine and you wait the timeout so that CF expires the Session A, the next time you visit, you will send back a CFID/CFTOKEN for the expired Session A, and CF will say "Hey, that session doesn't exist anymore, let me give you a new Session B CFID/CFTOKEN" and will update the cookies with the new values of Session B.
As we see with this situation, at this point, the user doesn't have access to any of the variables that were stored in SESSION A, because CF terminated it out of memory. And since SESSION B is freshly created, the only variables that exist in it are the ones created automatically by CF (CFID, CFTOKEN, URLTOKEN, etc.) as well as any variables you may have created and stored into the SESSION scope in the onSessionStart() method.
To clarify your last statement.
If a new session is starting because a person's session expired, it DOES mean that a NEW CFID/CFTOKEN are going to be returned to the user, thus updating thier CFID/CFTOKEN cookie on their machine with the new values, and giving them access to the new SESSION's variables.
Thanks for your explanation.
As per your comments once a session got expired new CFID/CFTOKEN values are generated. I created a sample application to check this where I set session time out as two mnts and that ssession got expired. But when I check the cookies in browser I am getting same values for CFID/CFTOKEN. But when I delete this I am getting new values. So just to know that whenever a session got expired , cant we see new updated CFID/CFTOKEN values in browser.??
I followed below steps.
1.Made a request for - http://localhost:8500/poc/nbt/
2.got new CFID/CFTOKEN values as 10901/13092563
3.After session timeout (2 mnts) I checked my browser cookies but I can see same values for CFID/CFTOKEN.
I had written files in onSessionEnd method also ( as given below ) to check whether I am getting new CFID/CFTOKEN values, but no luck its the same old values only.
<cffunction name="onSessionEnd" returnType="void">
<cfargument name="SessionScope" required=True/>
<cfargument name="ApplicationScope" required=False/>
<cffile action="write" file="C:/ColdFusion9/wwwroot/time_END.txt" output="#NOW()#">
<cffile action="write" file="C:/ColdFusion9/wwwroot/cfid_END.txt" output="#ARGUMENTS.SessionScope.CFID#"
Any I dea why this is happening so??
Let's say you set your session timeout to 2 minutes.
When you visit the page, you start a new session, CF generates a CFID/CFToken and SENDS that back to you in your first request's response.
When you visit a page before the session time's out, your browser sends the CFID/CFToken with the request, CF sees this, verifies its a live session, and doesn't issue you a new one.
If you wait the 2 minutes for a session to timeout, CF kills the session, but DOES NOT MESS with your Cookies. It doesn't matter, because they're invalid anyways.
When you make a request, you send the now old CFID/CFToken, CF sees that this does not correlate to a live Session, and generates a new CFID/CFToken which it sends back to you now and updates you cookies with the new values.
Just because a session times out on the server does NOT mean ColdFusion removes the cookies from the user's browser. It just states that "For that CFID/CFToken combination, the session no longer exists, so let me generate a NEW session for you and send you it's CFID/CFToken to correlate your visitor to the new SESSION scope.
Waiting for the timeout and checking your cookies should show the last cookies you had when you made a request. Nothing new.
In your onSessionEnd() method, it will BE the old values because when the session expires, that method gets a COPY of the SESSION and APPLICATION scope, (the SESSION that just expired) and that is the old CFID/CFToken data. CF is performing as one would expect. What is it you're trying to do? I think the problem here is you're not understanding how sessions work.
A SESSION, to CF is when it takes a provided CFIF/CFToken cookie from a user's request and checks to see if it is valid. If so, then any variables stored into the SESSION scope are made available to that request's processing. These cookies act as a way of your browser saying who they are. By default, Session values are stored in RAM.
When you don't make a request in the amount of time specified in the THIS.sessionTimeout value, CF does not mess with ANY cookies on your machine. It simply says. "Hey, those variables I was holding for the SESSION that was for THIS CFID and THIS CFToken, well, delete them. The session expired. The browser won't see anything different whatsoever until it makes another request.
When you make a request, again, your browser provides CF the CFID and CFToken cookies, but this time CF says "Hey, that session expired, so I'll make a new one for you (fires off the onSessionStart() method) and it sends back a new CFID and CFToken cookie to the user which now correlates to the new session. A session that will stay alive as long as the user makes requests within the timeout specified.
If you deleted your cookies, the SESSION would still be ALIVE, however it would just be inaccessible, and after the timeout value, CF would expire it. But if you deleted your cookies, upon making a request to the server, there would be NO CFID/CFToken cookies sent, so CF would create a new session for you and send you back a new CFID/CFToken.
Thanks a lot Aegis for this detailed explanation. Now I am pretty clear with a doubt that I had in my mind.