Reply to comment

Fast and Effective PHP Session Setup Example to Minimize Logouts and Problems

Wed, 05/05/2010 - 12:52 - peter | |

I have one site which uses PHP sessions identified by browser cookies to store user state information.  This allows the application to store a large amount of information efficiently, providing continuity for a complex user session without sacrificing performance, and without using the database.  Just reference the session like any other hash, and anything you stored is still there, no matter the complexity of the data type with no serialization required.

There are some issues that have to be addressed in order for this to work, especially when trying to optimize for performance and overcoming user browser misconfiguration and browser bugs.  Here are some suggestions I have.  The 6-minute video features my compelling narration on this fascinating topic.

Date Setup Errors Causing Logouts 

Some user computers will inevitably have the date set wrong (often many years into the past or future), and they at times "cleverly" will discard cookies that appear to the browser to have expired.  The solution to this is to set your cookies to expire at the last possible time.  This is represented by the timestamp value 2147483647.  The best way to enforce this is to set the cookie expiration date accordingly - after the session is started -- (this also overcomes the problem that sessions by default do not extend their cookie expiration dates with on successive page loads and a user's session can run out if set with a timeout due toe cookie expiration):

setcookie($session_name, $_COOKIE[$session_name], 2147483647 , $my_cookie_domain_ibs);

Restricting Cookies to Not Apply to Subdomains

In my case, I have images served from subdomains (img1.example.com and img2.example.com) and do not want any cookies to be passed to those subdomains.  In order to set this up properly, the cookie_domain must be set, which sometimes can also be done in the session_set_cookie_params call.  But in either case, this must be before the session is started. To achieve the effect I want, I needed to set the cookie domain to '' (the null string).  If you do not do this, or if you set the cookie to domain to the main site (which in my case is example.com), then there is an implicit . (period) applied that causes the cookie to be applicable to all subdomains.

Fast Storage of Session Information in Shared Memory

There are a variety of ways that sessions can store their information - the default is on the disk.  The simplest way to improve the performance is to store the information in shared memory.  On linux, this can easily by done by storing in /dev/shm or a subdirectory thereof that you create for this purpose (I use owner root group apache and set permissions to 770 for the directory) - make sure to configure this properly in php.ini with a line like

session.save_path = "/dev/shm/phpsession"

Don't forget to create this directory in rc.local because after a reboot, /dev/shm is wiped clean.  

You can also configure php to save its session information in another memory form like APC or memcached but I am satisfied with using /dev/shm for this application.  Of course, remember that in any case, if you ever reboot your machine, your users will lose their session information, so don't reboot unless necessary.

Server Side Session Storage Deletion Management

With my approach, the cookies and sessions on the browser can stay alive for a very long time -- the cookies are set to stay valid until 2038, in case some computers have their date set wrong!  However, on the server side a more conservative test is applied in order to delete inactive sessions.  Otherwise there is a risk that the storage directory will get too big, cluttered with long inactive sessions.  There's also a potential security risk for users who use public computers.  For this reason, the application only keeps the session data on the server for about 3 hours from the latest page load.  This is achieved by the gc_maxlifetime parameter which has to be set up before the session is started, ie:

ini_set('session.gc_maxlifetime',   3600);  // one hour time limit

You may also specify values for when the server cleans out its old sessions.  This is done with the strange settings gc_probability and gc_divisor:

 

ini_set('session.gc_probability', '1');
ini_set('session.gc_divisor', '1000');

In Summary, Example Session Initialization File

Here is the file that is called from the application from every php file that requires sessions.  Remember that this must be called before the session is started and before any SESSION variables are referenced.
	<?php
 
$session_name = 'PHPSESSID'; 
$session_exp_time = 10000 ; 
 
$previous_name = session_name($session_name);
 
ini_set('session.gc_maxlifetime',   $session_exp_time);
ini_set('session.gc_probability', '1');
ini_set('session.gc_divisor', '1000');
ini_set('session.name', $session_name);
ini_set('session.cookie_domain', '');
ini_set('session.cookie_lifetime', 0 );
 
session_set_cookie_params($session_exp_time, '/', '');
 
session_start();
 
if (isset($_COOKIE[$session_name]))
setcookie($session_name, $_COOKIE[$session_name], 2147483647 , '');

Reply

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for clevery testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.