Got a real head scratcher (at least, for me it is.)
Just experimenting a little bit, this isn't project related (yet), but something I'd like to code as reusable for future projects.
I'm attempting to write code that will clear session variables when the browser is closed, -AND- disassociate the session variables from the client by altering and expiring the cfid and cftoken cookies.
In my Application.cfc, I have the following:
onSessionStart: <cfif NOT StructKeyExists(session,"app")><cfinvoke component="components" method="setDirs" returnvariable="session.app"></cfif> <cfset oRequest = getPageContext().getRequest()> <cfset session.cookies = oRequest.getHTTPRequest().getCookies()> <cfcookie name="cfid" value="#session.cfid#"> <cfcookie name="cftoken" value="#session.cftoken#"> onSessionEnd: <cfloop index="local.cookiename" list="cfid,cftoken,cfmagic"><cfcookie name="#local.cookiename#" value="" expires="now"></cfloop>
In the page that loads, I have:
<cfset session.cookies = getPageContext().getRequest().getHTTPRequest().getCookies()> <cfoutput> <cfloop index="idx" array="#session.cookies#">#idx.getName()# = #idx.getValue()# - Expires: #idx.getMaxAge()#</cfloop> </cfoutput>
The above is where the error message "Cookies undefined in Session" appears. Didn't I just set session.cookies, twice?
I don't quite follow what you're doing, but you can't mess with cookies in onSessionEnd() because it - intrinsically - is not associated with a request... and you can't send cookies to the browser other than as part of a response to a request.
Adam Cameron. wrote:
I don't quite follow what you're doing, but you can't mess with cookies in onSessionEnd() because it - intrinsically - is not associated with a request...
Can't, or shouldn't? It's forcing a new CFID and CFTOKEN when the browser is closed and re-opened, so that part (at least) is doing what I want. If I shouldn't be doing this, then is there a better way to force new CFID/CFTOKEN after a browser is closed? I'm trying to do this because StructClear(session) by itself isn't working - session variables set in previous openings of the browser are still present. New CFID/CFTOKEN values at least disassociate the browser from previous sessions, which eventually are cleaned up after the session timeout.
To change a browser's cookies, you need to communicate with the browser. This is done when the CF server sends the HTTP response to a request from that browser.
onSessionEnd() - by its very nature - only runs when there isn't communcation with the browser, and hasn't been any communication from the browser for at least the [session timeout] period. So you can monkey with the cookie scope all you like in there, but the changes are never sent to the browser, because the browser has long since "left the building" as it were.
As HTTP is connectionless, and the browser doesn't communicate with the CF server anyhow (the browser only talks to the web server), there is no way for the CF server to know that the client has closed their browser. All that takes place on the client machine, and CF is sitting on the CF server. Even the web server doesn't know what's happening on the client UI.
What you can do is to set the cookies and the session to have very short timeouts, so that the expire quickly once there's no activity to refresh them.