The Session Handler Class

One of the many problems faced by web developers is that of persisting data across multiple accesses to one web site. This is difficult because the connection to the web server is terminated once the requested page is sent to the client. In PHP this problem can be over come by using the session module . These functions enable the developer to save variables associated with the current session and retrieve them the next time the same user makes a request. However, PHP's standard session management implementation uses the servers file system as the database medium in which to store the session information. While this method is ideal for a small site, it is somewhat inefficient for large sites handling hundreds, possibly thousands of users.

Fortunately PHP provides a way through the session_set_save_handler() function to change where and how session data is stored. The session handler class provides a template for storing this information in a MySql database. It also has the ability to check the integrity of the session and manage session expiration and garbage collection.

The source code for the Session Management Class can be found here:

session_handler.php

Instantiating the Session Management Object

To create an instance of the Session Management object you must use a reference. This is because the PHP uses the internal session save and read functions as callbacks. If you do not use a reference when instantiating the object, PHP will create a new instance of the Session Management object for each time one of the callback functions is invoked.

PHP – Instantiating the Session Management Object
$session = &new session;

The Purpose of the Session Management Object

The session management object is designed to be as transparent as and to be compatible with all scripts using PHP's standard session management functions. Once an instance of the Session Management Object has been created the PHP session management functions can be used as normal. Additionally the Session Management object requires an open connection to a MySql database containing the table necessary to store the sessions. The following query will create the necessary table in the database for the session management class to function:

SQL – Session Table
CREATE TABLE session (
    SessionId CHAR(32) PRIMARY KEY,
    Expire UNSIGNED INTEGER NOT NULL,
    Hash CHAR(32) NOT NULL,
    Data BLOB);

The following PHP script is all that is necessary to activate the session management object.

PHP – Minimal Session management
mysql_connect('host', 'user', 'password');
mysql_select_db('session_db_name');

$session = &new session;

session_start();

Properties

The following properties affect the behaviour of the session management object:

db_link (resource)

If set, the session handler will use the pre established connection to a MySql database, pointed to by db_name. If this property is left unset, the link from the most recent call to mysql_connect() will be used.

db_name (string)

If set, the session handler will use the database with this name. If this property is left unset, the current database will be used.

database_ttl (integer) default: 0

Determines how long in minutes after a session has expired, the session should exist in the database. If set to 0, expired sessions will never be deleted.

hash_text (string) default: CLIENT_IP + USER_AGENT

This property is used to determine the session hash. The session hash is used to determine the integrity of the session to help protect against spoofing.

The hash is calculated using the hash_text and the session ID of the current session. If the session hash between two client requests is different, this can signify a spoof attempt.

ttl (integer) default: 0

Determines the length of time in minutes before a session expires. A session is said to have expired if the amount of time between the previous and the current request is greater than the ttl. If set to 0, the session will never expire.



Methods

is_expired()

Returns true if the current session has expired and false otherwise. If the session has expired, the expiry time is not updated in the session database.

un_expire()

Updates the expiry time in the session database. This function should be used to reset an expired session.

is_bad_hash()

Returns true if the current session hash does not match the hash stored in the database. A bad hash does not remove the session from the database.

is_new()

Returns true if the current request created a new session in the session database.

Example

The following PHP script demonstrates the use of the session handler class.

PHP – Session Handler
<?php
    include_once 'session_handler.php';

    mysql_connect('dbhost', 'username');
    mysql_select_db('dbname');
    
    /* instantiate the session handler object - it will now take over as the session handler */
    $session = &new session_handler;

    $session->ttl = 2; /* set expire time to two minutes */
    
    isset($_GET['operation'])?$operation=$_GET['operation']:$operation='';

    if ($operation == 'badhash') {
        $session->hash_text = 'bad'; /* simulate a bad hash by changing the hash text */
    } else if ($operation == 'removesession') {
        /* clear the session ID and delete the session */
        session_id(NULL);
        session_destroy();
    }
        
    /* start the session */
    session_start();
?>
<html>
    <head>
    </head>
    <body>
<?php
    if ($operation == 'unexpire') { /* reset the session expiry time */
        $session->un_expire();
    }

    if ($session->is_new()) { /* test for a new session */
        echo ('<p>This is a new session. Your session ID is ' . $this->sid);
    }

    if ($session->is_expired()) { /* test for an expired session */
        echo ('<p>Session has expired.</p>');
        $_SESSION = Array();
    } else if ($session->is_bad_hash()) { /* if a bad hash is detected - nuke the session */
        session_destroy();
        echo ('<p>Bad Session hash.</p>');    
    }
    
    isset($_POST['action'])?$action=$_POST['action']:$action='';

    switch ($action) {
        case 'set': /* set a session variable */
            $_SESSION[$_POST['varname']] = $_POST['value'];
            
            echo ("<p>{$_POST['varname']} saved.</p>");
            break;
        case 'get': /* retrieve a session variable */
            $name = $_POST['varname'];
            echo ("<p>$name = " . $_SESSION[$name] . '</p>');
            break;
    }
            
?>
<form method="post" action="<?php echo ($_SERVER['PHP_SELF'] . (SID?'?' . SID:'')); ?>">
    Variable Name: <input type="text" name="varname" /><br />
    Value: <input type="text" name="value" /><br />
    Action: <select name="action">
        <option value="set">Set Session Variable</option>
        <option value="get">Retrieve Session Variable</option>
    </select><br />
    <input type="submit" />
</form>
<a href="<?php echo ("{$_SERVER['PHP_SELF']}?operation=badhash" . (SID?'&' . SID:'')); ?>">Simulate Bad Hash</a>
<a href="<?php echo ("{$_SERVER['PHP_SELF']}?operation=unexpire" . (SID?'&' . SID:'')); ?>">Unexpire Session</a>
<a href="<?php echo ("{$_SERVER['PHP_SELF']}?operation=removesession" . (SID?'&' . SID:'')); ?>">Remove Session</a>
    </body>
</html>