CakePHP and the Session.timeout SNAFU

As I’ve mentioned before, my CMS, cms34, is built on the CakePHP framework. I love CakePHP, but it’s not perfect.

A client contacted me last week, reporting that customers using her website — specifically, a complex form that might take 30 or more minutes to complete — were having their sessions timeout during that process. Now, yes, you may point out (and you would be right) that this is an excellent scenario for using AJAX to save a draft of the users’ form data, or at least ping their session to keep it alive. And you would be correct. But there are two reasons I did not take this path in response to the problem: 1) I’m trying to remember to follow the web standards principle that JavaScript should be used only to enhance functionality, but the site should still work even with it turned off (though in practice I often forget to honor this principle), and 2) the site is in its peak of activity this week, and it would be daft to implement a major functionality change in the form right now — not enough time for adequate testing.

So, the task at hand was simply to increase the session timeout period, so users could stay on the form for a longer time without losing their sessions.

Seems easy enough. The CakePHP config.php file has some settings that play directly into this: Session.timeout and Security.level.

Session.timeout is an integer representing the number of seconds in the session. Well, not exactly. It’s a multiplier value, and the actual session timeout duration is determined by multiplying Session.timeout by the value associated with Security.level, which itself has three possible values: high, medium and low, corresponding respectively to ×10, ×100 and ×300.

I already had Security.level set to low and Session.timeout set to 1800, so really, the sessions should have stayed alive for over six days of inactivity. And yet, sessions were timing out after about 20 minutes. What gives?

What gives is another value in the config.php file: Session.save.

CakePHP offers a number of ways to store session data, but the default value is php, which means it uses the built-in session functionality in PHP. The problem is, PHP has its own session timeout setting (in the php.ini file), and frankly my dear, PHP doesn’t give a damn what CakePHP’s session timeout setting is. And so, with Session.save left at its default php value, my sessions were timing out after 20 minutes (the PHP default) no matter what I changed in config.php.

So, an experiment: I decided to change Session.save to cake, which tells it to use CakePHP’s own session cache, located inside your CakePHP application under app/tmp/sessions. (Be sure that path is fully writable by Apache!)

Success! I left a browser window open on my test site overnight, and the session was still active the next morning. But along the way in my troubleshooting, I had changed my Session.timeout value to 14400, which when combined with the Security.level setting of low (that is, when multiplied by 300), had my sessions enduring for a ridiculously long 50 days! Some quick work with a calculator (although, in retrospect, I ought to have been able to divide 14400 by 50 in my head) told me to set Session.timeout to 288 if I wanted my sessions to last for 24 hours.