Stackable Session Handlers
This is not a class, but an interface (along with some example implementations).
It extends the standard PHP Session Handler interface to add the capability to layer multiple
handlers implementing different functionality. The resulting stack allows you to fine tune your
performance and functionality to meet your exact needs using standard components.
Examples of the things which might be implemented at different layers are:
- storage
- replication
- merging of private and common data stores
- encryption
- security checking
- more.....?
The revised interface looks like this:
<?php
StackableSessionHandler implements StackableSHInterface {
public __construct ( [ StackableSessionHandler $SHnext ] ) // added
public integer lastAccessed ( [ integer $lastAccess ] ) // added
public bool close ( void )
public string create_sid ( [ string $newSID ] ) // amended
public bool destroy ( string $session_id )
public bool gc ( int $maxlifetime )
public string read ( string $session_id )
public bool write ( string $session_id, string $session_data )
public bool install ( [bool $use_create_sid=true] ) // added
}
Constructor
Each constructor can be invoked with an object implementing the interface allowing the handlers to be stacked. Calls to each method are propogated to the lower objects. Only the topmost object
is bound using session_set_save_handler().
lastAccessed
The lastAccessed() method should return the Unix timestamp for when the session was last written.
This method will typically return a value which is populated by the read() method - and hence should not be invoked prior to that (i.e. at session_start()).
If a value is passed, then an object in the stack may replace this with its
own lastAccess time or leave it as is. It is up to the class author to decide
what action to take and whether to take the action before, after or both relative
to calling the next component in the stack.
This method is critical to the operation of both the securityChecker and
writeSometimes example implementations.
install
The install() method provides an simpler way to hook into the session handler than via session_set_save_handler() and is the recommended
way to enable the custom session handler.
Normally the bottom most handler will be a storage handler.
The example classes are written to accomodate the possibility that the bottom-most component only implements the standard interface, however note
that handlers which depend on knowing the lastAccess time will not work as expected.
Usage
This code demonstrates creating a stack with a security layer on top of a storage layer
<?php
require_once("handlers/sesspp.inc.php"); // base class
require_once("handlers/security.inc.php"); // do additional security checks on session
require_once("handlers/nonBlocking.inc.php"); // storage
$storage=new nonBlockingHandler();
$check=new securityHandler($storage); // note that the lower component in the stack is passed to the constructor
session_start();
...
Example Implementations
In the examples below, refreshing the screen should increment a session counter. Every third refresh should trigger a regeneration of the session id.
- The compatible handler - behaves like the builtin session handler
- The non-blocking handler - similar to the builtin handler but without file locking
- The Write Sometimes handler - only writes the session data when necessary (NB does not implement storage)
- The Security Checking handler destroys the session if the IP address or Browser change (NB requires PHP 5.5.4 or later since it adds data into the session, does not implement storage)
- The Encrypting handler provides a vry high level of confidentiality to session data. It does not implement storage.
- The Null handler does nothing other than pass on the calls to the lower components, but is provided as a template for building your own plugins.
Except for a conflict when the non-blocking handler tries to access the same file as the compatible handler, you can use all of these at the same time! Indeed
if you overwrite the path in one of the file-based storage handlers, you could even use them all - and have replicated sessions.