Home > PHP > PHP session maxlifetime

PHP session maxlifetime

September 2, 2009 Leave a comment Go to comments

A PHP Session Cookie (mostly defined as PHPSESSID) has a default life time until the browser is closed. This is OK for many web-applications, but in some cases this is not wanted and the lifetime can be changed – we will cover this later.

Another session-relevant issue is the PHP garbage collector. When a session is created, a flat-file is created on the server – e.g. in /tmp on linux servers. Since the session ID is a unique identifier, those session files will accumulate over time – the garbage collector will take care of these files and delete old files from time to time. PHP has a sort of built-in “load-balancing” feature for this garbage collector, so that old session files are not deleted on each and every session request, but with a certain probability. The default timeout for session files is 1440 seconds or 24 minutes. So a session file can be deleted after that timeout, but it may reside on the server longer, depending on the amount of sessions created – here comes the probability into the game.

//
//
So we have a session cookie with a lifetime until the browser is closed, but the garbage collector might delete the session file much earlier. In this case, and if there is a session request after the session file has been deleted, a new session is created and the old session information is lost. This can be very annoying if e.g. the users is writing some message in a web-based interface and this task takes longer than the session file on the server is available.

There are 3 PHP.ini variables, which deal with the garbage collector:

PHP ini value name default Changeable
session.gc_maxlifetime 1440 seconds PHP_INI_ALL
session.gc_probability 1 PHP_INI_ALL
session.gc_divisor 100 PHP_INI_ALL


session.gc_probability in conjunction with session.gc_divisor is used to manage probability that the gc (garbage collection) routine is started. The probability is calculated by using gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that the GC process starts on each request.

The most important variable is session.gc_maxlifetime:
As discussed earlier, this variable sets the timeout for session file deletion.
All three variables can be set in the php.ini configuration file, but more important, those can be also set during runtime due the PHP_INI_ALL permission.

//
//

$garbage_timeout = 3600; // 3600 seconds = 60 minutes = 1 hour
ini_set('session.gc_maxlifetime', $garbage_timeout);

So we just changed the garbage collection timeout to one hour. There is just another problem. Since PHP stores all session files into one directory (e.g. /tmp on Linux) and the garbage collector can’t tell the difference between the different gc_maxlifetime’s of the individual session files, the session files are deleted by the garbage collector with the lowest timeout.

The solution for this problem is another session file directory. This is best accomplished by creating another directory *within* the regular session file directory.
First we read the current save path for the session files and append our own directory to this path. Note: In order to make that platform independent, we need to check for the file-seperator first. Now we check if the directory already has been created, if not, create one. Then we set the new path for the session files.

strstr(strtoupper(substr($_SERVER["OS"], 0, 3)), "WIN") ?
	$sep = "\\" : $sep = "/";
$sessdir = ini_get('session.save_path').$sep."my_sessions";
if (!is_dir($sessdir)) { mkdir($sessdir, 0777); }
ini_set('session.save_path', $sessdir);

Now our session files are stored in the new directory and the regular garbage collector will not see them, so those files will survive at least that long as defined in gc_maxlifetime.

If you have enough disk space on the server you can set the session file timeout really long, in order to preserve most/all sessions until the browsers are closed. But in many cases the session should expire after a certain time, so we have to change the life-time of the session cookie itself.

$cookie_path = "/";
$cookie_timeout = 60 * 30; // in seconds
session_set_cookie_params($cookie_timeout, $cookie_path);

(the cookie path can be “/” or e.g. “/somedirectory” if the cookie should be valid for a certain directory only)

NOTE: All these changes MUST be made before the actual session is opened with session_start() or session_register().

Conclusion:
So we have a session cookie with a custom-defined lifetime, and we also redefined the garbage collector timeout. This ensures that the current session data (identified with the session id PHPSESSID) is available at least as long as the session cookie in the browser is valid.

Last but not least, we have the example source code session.php, which shows all steps together.

//
//
session.php

<?
// path for cookies
$cookie_path = "/";

// timeout value for the cookie
$cookie_timeout = 60 * 30; // in seconds

// timeout value for the garbage collector
//   we add 300 seconds, just in case the user's computer clock
//   was synchronized meanwhile; 600 secs (10 minutes) should be
//   enough - just to ensure there is session data until the
//   cookie expires
$garbage_timeout = $cookie_timeout + 600; // in seconds

// set the PHP session id (PHPSESSID) cookie to a custom value
session_set_cookie_params($cookie_timeout, $cookie_path);

// set the garbage collector - who will clean the session files -
//   to our custom timeout
ini_set('session.gc_maxlifetime', $garbage_timeout);

// we need a distinct directory for the session files,
//   otherwise another garbage collector with a lower gc_maxlifetime
//   will clean our files aswell - but in an own directory, we only
//   clean sessions with our "own" garbage collector (which has a
//   custom timeout/maxlifetime set each time one of our scripts is
//   executed)
strstr(strtoupper(substr($_SERVER["OS"], 0, 3)), "WIN") ?
	$sep = "\\" : $sep = "/";
$sessdir = ini_get('session.save_path').$sep."my_sessions";
if (!is_dir($sessdir)) { mkdir($sessdir, 0777); }
ini_set('session.save_path', $sessdir);

// now we're ready to start the session
session_start();

session_register('mytest');
print "mytest=".$_SESSION['mytest']."<br><br>";
$_SESSION['mytest'] = "captain";
?>

source: http://www.captain.at/howto-php-sessions.php

About these ads
Categories: PHP
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: