ColdFusion sessions are not timing out? Why not? - coldfusion

I am using ColdFusion 8. I am using this line to timeout sessions:
<CFAPPLICATION NAME="XXX"
CLIENTMANAGEMENT="NO"
SESSIONMANAGEMENT="Yes"
sessionTimeout="#CreateTimeSpan(0,0,1,0)#">
I am creating a session like this:
if (not structKeyExists(SESSION, "UserInfo")) {
SESSION.UserInfo = structNew();
}
I expect that my session will timeout after one minute. This is not working properly. I've tried every combination of numers, but my sessions NEVER time out. Even after not working all weekend (and shutting down my browser), my session is still up and running.
Why might my sessions not be timing out?
EDIT ~ My proof that my sessions are not timing out is that I can access a site with specific info in the session scope and it will never die, even after weeks of not using that browser.
We have three sites with three distinct names 1) XXXProd, 2) XXXStage, and 3) XXXDev.

Have you considered switching to J2EE sessions?
<cfscript>
session.setMaxInactiveInterval(1);
getPageContext().getSession().invalidate();
</cfscript>
<cfcookie name="jsessionid" expires="now">
<cflocaton url="/" addtoken="false">
That will not only kill of the cookie and ColdFusions knowledge of the session, it will kill the underlying session as well. You also don't need to have a "sessionless" page request that way.
With your current situation, in Server Monitor can you see sessions being created and destroyed?

Related

Using multiple SessionTimeout in Coldfusion

I have an application which has different types of users. I need to set sessionTimeout based on user type. For example admin 30 minutes, user 10 minutes. To do this, I gave a default sessionTimeout of 30 minutes in application.cfc
<cfcomponent output="false" extends="org.corfield.framework">
<cfset this.applicationTimeout = createTimeSpan(1,0,0,0) />
<cfset this.sessionManagement = true />
<cfset this.sessionTimeout = createTimeSpan(0,0,30,0) />
.............
............
</cfcomponent>
When I dump the application variables I can see sessionTimeout is 600 which is correct. Now in the onRequestStart method, I wrote a code to check the loggedIn user type and set the sessionTimeout accordingly.
<cfif StructKeyExists(session,"user") AND ListLast(CGI.HTTP_REFERER,"/") EQ "login.cfm" >
<cfif session.user.userType EQ "GSA">
<cfset this.sessionTimeout = createTimeSpan(0,0,10,0) />
</cfif>
</cfif>
After this when I dump application variables, sessionTimeout is showing in days not in seconds. And also session is not getting ended after 10 minutes.
Can someone help on this? How to implement two different sessionTimeout in an application? Also why it is showing the sessionTimeout in days instead of seconds once I set the sessionTimeout again?
I don't believe there is any way to modify this scope metadata from inside one of these functions: onApplicationStart, onSessionStart or onRequestStart. Meaning you can't set this.sessionTimeout in any of those methods.
I was recently looking into this ColdFusion 11: Changing Application "this" Scope metadata from different functions in extended Application.cfc. However metadata is set for every request made by ColdFusion. Meaning you can try an approach like mentioned in this article, by Ben Nadel, and move the logic that sets the timeout out of onRequest() and onto the this scope and try creating dynamic session timeouts.
Delaying ColdFusion Session Persistence Until User Logs In
You are probably going to have to get creative in figuring out which user is logging in at that point though. ( Even if authentication occurs later ... any harm in setting a timeout?)
Session timeouts are common for all users. The timeout duration is set application-wide when the first request comes.
I think the short answer is, you cannot set two different session timeout durations.
Here is one method you can use. It's kind of creating your own session management client side, but it would allow for custom session timeouts per user role.
Create a timestamp in the session scope that is initially set to the current time a user logs on to your app. In your app's client JavaScript, create a timer that calls a function every minute or so that in turn calls a server side function to see how much time has elapsed since the last recorded timestamp for that user. If the time elapsed reaches the maximum allowed for that user's role, use the JavaScript function to logout the user.
With this method you reset the timestamp each time the user "interacts" with the app (runs a script, calls a cfc library function, etc.), such that the user does not get logged out while actively using the app. The user is only logged out after "x" minutes of inactivity that you define, and the function you call on the server side can further define what that number is per user role.
I've used this in railo but i think it applies to coldfusion too.
getPageContext().getSession().setMaxInactiveInterval(javaCast("int", 60));
It basically sets the session time out value of the currently running request to 60 something (i can't remember if it's in minutes or seconds)

How do I determine if a scheduled task was ran automatically or ran in a browser?

I am running some code as a scheduled task, setup in CF Administrator.
Is there a way to tell in the code that the code ran as a scheduled task, whether it was ran by clicking the run icon in the CF Administrator scheduled task area, or whether it was called directly in a browser?
Adding additional variables will not work?
From the test link in the CF admin
If you're asking if you can identify the difference between a scheduled task being run manually by clicking the test link in the coldfusion admin or run on schedule, you can enable logging of scheduled tasks. Any time the task is run by the user the log entry will say [name of job] Executing because of user request at {timestamp}. If it ran naturally, the log entry will say [name of job] Executing at {timestamp}
I've looked for a way to tell by code and I can't find anything. It would depend on the accuracy of the scheduler but you could look to see if now() is equal to the time of the schedule. Something like (pseudo code):
<!--- disclaimer: I've heard stories that cfschedule sometimes runs a little late --->
<cfset scheduleTime = "2:00 am">
<cfif cgi.HTTP_USER_AGENT eq "CFSCHEDULE" and timeFormat(now(), "h:mm tt") eq scheduleTime>
<!--- ran naturally --->
<cfelse>
<!--- ran by force --->
</cfif>
From a browser
If you want to know if your scheduled task was run by the schedule or if the file was hit by the browser you can look at cgi.HTTP_USER_AGENT. if it is run by the scheduler it will equal CFSCHEDULE otherwise it will equal whatever the client is set to send.
Perhaps, Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11
or if you're lucky enough to have a bot hit it, something like: Mozilla/5.0 (compatible; MJ12bot/v1.4.3; http://www.majestic12.co.uk/bot.php?+)
It is possible to spoof the client or server request to make the user user agent to say CFSCHEDULE but it isn't likely.
on a side note...
The default user agent for cfhttp is "COLDFUSION", in case you were interested.

Can we renew session in Coldfusion?

I am storing 5-6 variable values in my session. Any suggestions on how can I renew my session struct when its about to expire? I am using Coldfusion 8.
Thanks!!
Use AJAX to ping the server to keep the session alive
Or just simply extend the session timeout timeSpand.
Any call to a CFM page from that session would cause the session to be extended. What I have seen done is a JS timer will be running and end shortly before the session expires. When the timer runs up it triggers a popup that loads a non CFM page(basic HTML) and that page states a message about the session ending soon and asking the user if they'd like to continue it.
Here's an idea of what Ajax to automatically ping the server could look like (as suggested in Henry's answer.)
//This function will keep the session alive as long as the page is still open.
//Whenever the page nears expiration, it automatically extends it.
function autoExtendSession(days,hours,mins,secs){
var milliseconds = (days*86400000)+(hours*3600000)+(mins*60000)+(secs*1000);
setTimeout(
function(){
$.post("server/heartbeat.cfm");
console.log("Heartbeat sent to the server.");
//Start another timer.
autoExtendSession(days,hours,mins,secs)
//Once we are 98% of the way to the timeout, the heartbeat is sent.
//This way the timeout should never actually be reached.
}, milliseconds-(milliseconds*0.02));
};
The hearbeat.cfm page doesn't actually have to contain anything, the server will renew the session when the $.post hits it, whether or not it has content.
Exact way of doing what you are asking for is to push session data into the database when onSessionEnd fired and restore it on next onSessionStart. To find out the data entries to read you can put cookie into the user's browser with unique identifier (for example, salted+encrypted id of that entry), kind of "Remember me" stuff.
You could try setting your session timeout to something small, say 5min.
Then when someone authenticates, extend the session timeout to something larger, 30min.
And if they signout, drop it back down.
eg. configure your cf admin with a 5 minute session timeout.
On sign in:
<cfscript>
// extend session timeout to 1800 seconds (30min)
session.SetMaxInactiveInterval( javaCast( 'long', 1800 ) );
</cfscript>
On sign out:
<cfscript>
// shrink session timeout to 300 seconds (5min)
session.SetMaxInactiveInterval( javaCast( 'long', 300 ) );
</cfscript>
The session hangs around for another 5 minutes and then is cleaned up.
Unless you continue using the site, in which case each page request would give you a further 5min.

How to restart Coldfusion Application Server when application times out?

Is there any way to restart the CF server through the Application.cfc, when the application times out? As per Adobe documentation, they showed as follows:
<cffunction name="onApplicationEnd">
<cfargument name="ApplicationScope" required=true/>
<cflog file="#This.Name#" type="Information"
text="Application #Arguments.ApplicationScope.applicationname# Ended" >
</cffunction>
What I would like to do is replace the <cflog> above with <cfexecute> as follows:
<cfexecute name = "C:\CFRestart.bat"
outputFile = "C:\output.txt"
timeout = "1">
</cfexecute>
So OnApplicationEnd will run the CFRestart.bat file when the application times out. Is this possible or not?
onApplicationEnd is not likely to be reached unless you have a very quiet application because every time someone access the application the timeout is reset.
I'd be very uncomfortable using an application to restart a coldfusion instance. I can see all sorts of horrible security issues etc looming. To be honest I'm not really sure why you'd want to restart the server if your application end.
Also, according to the docs onApplicationEnd is called when the server is restarted, so if you did get this working, when you restart your server the application would also have a go at restarting your server. This would get very messy.
Don't believe you can call the .bat script from ColdFusion. Because once it stops the service the <cfexecute> will also terminate (think it runs under the CF service), never reaching the restart.
Guessing you have a server that routinely fails because you're hitting an Out of Memory (OOM) exception. To get over the hump in those situations I setup as batch script as a Windows Scheduled Task (see the first answer there for how) that restarts the server periodically, say every 24, 12, or 6 hours. Choose an interval that makes sense for your situation.
Assuming OOM is the root cause, I suggest downloading a Java JDK, configuring ColdFusion to use it (i.e. jvmhome in jvm.config file), and passing parameters to enable a JMX connection. You use this JMX connection to monitor ColdFusion using Visual VM, which comes with the JDK. From there you can generate a heap dump file and/or tell the VM to generate one on OOM. Tehn I've had very good success running that through the Eclipse Memory Analyzer Tool, which has a suspected leaks report that more than once has helped track down the root cause of server OOM crashes.
If that is not your scenario then I suggest enabling snapshots if you're using ColdFusion enterprise, otherwise cfstat is you friend on standard. For either one, you can also setup probes that send a notification when the server is running slowly. This can help you connect to the server in question and generate a dump at the appropriate time or identify if the problem is load related instead.
This may not be your answer, but I use this often to help the garbage collection in JVM memory.
Set this as a scheduled task to run every 5 minutes, and i never get jvm memmory problems anymore.
<cfparam name="url.maxused" default="999">
<cfparam name="url.minfree" default="300">
<cfif NOT isDefined("runtime")>
<Cfset runtime = CreateObject("java","java.lang.Runtime").getRuntime()>
</cfif>
<cfset fm = runtime.freememory()/>
<Cfset fm = int((fm/1024)/1024)/>
<cfset usedmem = 1270-fm/>
<cfoutput>
#Now()#<br>
Before<br>
Free: #fm# megs<br>
Used: #usedmem# megs<br>
</cfoutput>
<br>
<!--- check if we are using too much memory --->
<cfif usedmem gt url.maxused or fm lt url.minfree>
<cfset runtime.gc()>
Released Memory<br>
<cfelse>
No need to release memory using the thresholds you provided<br>
</cfif>
<br>
<cfset fm = runtime.freememory()/>
<Cfset fm = int((fm/1024)/1024)/>
<cfset usedmem = 1270-fm/>
<cfoutput>
After<br>
Free: #fm# megs<br>
Used: #usedmem# megs<br>
</cfoutput>
This has been hanging around unanswered for an age, so I thought I'd help getting it cleared up.
First, this:
"Server Error The server encountered an internal error and was unable to complete your request. Could not connect to JRun Server."
This is NOT an application timeout, this is just the server becoming unresponsive, or running out of memory, or just encountering something it doesn't like. But it's nothing to do with the application timing out.
The application times out when there's been no activity (ie: no page requests... no visitors) on that site for longer than the application timeout period, which by default is two days (or whatever you have set in your Application.cfc).
Now... I can understand why you might want to recover if your server becomes unresponsive, bur you're approaching this from the wrong angle. Intrinsically if the server ain't working, you can't use that server to do anything (like cure itself)! What is generally done here is that some other process checks that the server is responsive, and if that service determines the server is not responsive, issues a restart.
So you should look at some other software which can perform an HTTP request to your CF server, and if the reaction to the HTTP request suggests the CF server is unresponsive, then the monitoring software tells CF to restart.
To add to the answer by Stephen Moretti and may be the possible solution you were looking for to your interesting question above:
Will the OnApplicationEnd run CFRestart BAT file when application is
timeout?
The straight answer is no. Since the OnApplicationEnd() event is a part of the Application's life cycle, so when the application itself is timed out, there is no event that will be called here. This must be clear.
Getting straight to your question though, yes, you can make a custom script file run on the event of an application timeout or end (whatever is the case). You will have to deal with the Serve Scope here.
First up, the application doesn't timeout, a page request does. On request timeout the onApplicationEnd() function is not called. That is only called if the application is shutting down. Here is some info on the CF application life cycle.
Second, in my experience, restarting application servers for whatever reason is probably masking your real problem. If you application is running slow / crashing etc. then I suggest you look into the real reason this is happening rather than restarting it.
However, I can't think of a reason this would not work in principle, but I would suggest you conduct a quick test if this really is what you wish to do.
Hope that helps.

How can I timeout Client-scoped variables in Coldfusion?

I apologize if this is a "duh" question. It seems like the answer should be easily googleable, but I haven't found it yet.
I am working on a large Coldfusion application that stores a large amount of session/user data in the Client scope (ie <cfset Client.UserName = "JoshuaC"> ). I did not write this application, and I don't have the luxury of significantly refactoring it.
I've been given the task of setting the Client variables to time out after 72 hours. I'm not entirely sure how to do this. If I had written the application, I would have stored the variables in the Session scope, and then changed the sessiontimeout attribute of the CFAPPLICATION tag. As it is though, I'm not sure if that timeout affects the Client variables, or what their level of persistence is. The way the application works now, the Client variables never time out, and only clearing the user's cookies, or visiting a logout page which sets all the Client-scoped application variables to "", will clear the values.
Of course, I could create some kind of timestamp variable like Client.LastAccessDateTime, and put something in the Application.cfm to clear the client variables if that datetime is more than 72 hours prior to Now(). But there's got to be a better way, right?
Depending whether your are using a datasource or registry as a Client Store you have to set the "Purge data for clients that remain unvisited for 90 days to 3 days (=72 hours) on the
ColdFusion Administrator => Client Variables => Registry
or
Client Variables => NameOfDatabase Page.
If Client Variables are stored as cookies, then you have to adjust the expires period, when setting the cookie.
The Purge Interval on the Client Variables page only controls how often ColdFusion executes a purge operation on your client stores (= seeks for expired Client Variables in order to delete them).
I suppose you are looking for Purge Interval setting, which is configured in CF Administrator at Server Settings > Client Variables page. Default interval is 1 hour 7 min.
EDIT: This setting value is not exactly what you need. I'm sorry, see my comment about purging -- think it is more accurate.