Zebra_Session Zebra Session

Class: Zebra_Session

source file: /Zebra_Session.php

A drop-in replacement for PHP's default session handler, using MySQL for storage and providing better performance, better security and protection against session fixation and session hijacking.

Works with or without PDO.

Read more here.

Author(s):

Version:

  • 4.0.1 (last revision: September 23, 2023)
    See CHANGELOG

License:

Copyright:

  • © 2006 - 2023 Stefan Gabos

Class methods

constructor __construct()

void __construct ( resource &$link , string $security_code , [ integer $session_lifetime = 0 ] , [ boolean $lock_to_user_agent = true ] , [ boolean $lock_to_ip = false ] , [ int $lock_timeout = 60 ] , [ string $table_name = 'session_data' ] , [ boolean $start_session = true ] , [ boolean $read_only = false ] )

Constructor of class. Initializes the class and, optionally, calls session_start()

  1. // first, connect to a database containing the sessions table, either via PDO or using mysqli_connect
  2.  
  3. // include the class
  4. // (you don't need this if you are using Composer)
  5. require 'path/to/Zebra_Session.php';
  6.  
  7. // start the session
  8. // where $link is a connection link returned by mysqli_connect or a PDO instance
  9. $session new Zebra_Session($link'sEcUr1tY_c0dE');

The following configuration options are set by the library when instantiated:

  1. // only when over HTTPS
  2. ini_set('session.cookie_secure'1);
  1. // don't expose the cookie to client side scripting making it harder for an attacker to hijack the session ID
  2. ini_set('session.cookie_httponly'1);
  1. // make sure that PHP only uses cookies for sessions and disallow session ID passing as a GET parameter
  2. ini_set('session.use_only_cookies'1);

The following configuration options are recommended to be set before instantiating this library:

  1. // disallows supplying session IDs via `session_id('ID HERE')
  2. ini_set('session.use_strict_mode'1);`

By default, the cookie used by PHP to propagate session data across multiple pages (PHPSESSID) uses the current top-level domain and subdomain in the cookie declaration.

Example: www.domain.com

This means that the session data is not available to other subdomains. Therefore, a session started on www.domain.com will not be available on blog.domain.com. The solution is to change the domain PHP uses when it sets the PHPSESSID cookie by calling the line below before instantiating the Zebra_Session library:

  1. // takes the domain and removes the subdomain
  2. // blog.domain.com becoming .domain.com
  3.     'session.cookie_domain',
  4.     substr($_SERVER['SERVER_NAME']strpos($_SERVER['SERVER_NAME']'.'))
  5. );

From now on whenever PHP sets the PHPSESSID cookie, the cookie will be available to all subdomains!

Arguments
resource &$link

An object representing the connection to a MySQL Server, as returned by calling mysqli_connect, or a PDO instance.

If you use Zebra_Database to connect to the database, you can get the connection to the MySQL server via Zebra_Database's get_link method.

string $security_code

The value of this argument is appended to the string created by concatenating the user browser's User Agent string (or an empty string if lock_to_user_agent is FALSE) and the user's IP address (or an empty string if lock_to_ip is FALSE), before creating an MD5 hash out of it and storing it in the database.

On each call this value will be generated again and compared to the value stored in the database ensuring that the session is correctly linked with the user who initiated the session thus preventing session hijacking.

To prevent session hijacking, make sure you choose a string around 12 characters long containing upper- and lowercase letters, as well as digits. To simplify the process, use this link to generate such a random string.

integer $session_lifetime

(Optional) The number of seconds after which a session will be considered as expired.

A session is active for the number of seconds specified by this property (or until the browser/browser tab is closed if the value is 0) OR the session has been inactive for more than the number of seconds specified by session.gc_maxlifetime.

This property sets the value of session.cookie_lifetime.

Expired sessions are cleaned up from the database whenever the garbage collection routine runs. The probability for the garbage collection routine to be executed is given by the values of gc_probability and gc_divisor.

To easily check the values of session.gc_maxlifetime, gc_probability and gc_divisor for your environment use the get_settings() method.

Default is 0 - the session is active until the browser/browser tab is is closed OR the session has been inactive for more than the number of seconds specified by session.gc_maxlifetime.

boolean $lock_to_user_agent

(Optional) Whether to restrict the session to the same User Agent (browser) as when the session was first opened.

The user agent check only adds minor security, since an attacker that hijacks the session cookie will most likely have the same user agent.

In certain scenarios involving Internet Explorer, the browser will randomly change the user agent string from one page to the next by automatically switching into compatibility mode. So, on the first load you would have something like:

  1. Mozilla/4.0 (compatibleMSIE 8.0Windows NT 5.1Trident/4...

and reloading the page you would have

  1.  Mozilla/4.0 (compatibleMSIE 7.0Windows NT 5.1Trident/4...

So, if the situation asks for this, change this value to false.

Default is true.

boolean $lock_to_ip

(Optional) Whether to restrict the session to the same IP as when the session was first opened.

Use this with caution as users may have a dynamic IP address which may change over time, or may come through proxies.

This is mostly useful if you know that all your users come from static IPs.

Default is false

int $lock_timeout

(Optional) The maximum amount of time (in seconds) for which a lock on the session data can be kept.

This must be lower than the maximum execution time of the script!

Session locking is a way to ensure that data is correctly handled in a scenario with multiple concurrent AJAX requests.

Read more about it here.

Default is 60

string $table_name

(Optional) Name of the MySQL table to be used by the class.

Default is session_data

boolean $start_session

(Optional) Whether to start the session right away (by calling session_start())

Default is true

boolean $read_only

(Optional) Opens session in read-only mode and without row locks. Any changes made to $_SESSION will not be saved, although the variable can be read/written.

Default is false (the default session behavior).

top

method get_active_sessions()

integer get_active_sessions ()

Gets the number of active (not expired) sessions.

The returned value does not represent the exact number of active users as some sessions may be unused although they haven't expired

  1. // get the number of active sessions
  2. $active_sessions $session->get_active_sessions();
Tags
return:   Returns the number of active (not expired) sessions.
top

method get_settings()

array get_settings ()

Queries the system for the values of session.gc_maxlifetime, session.gc_probability, session.gc_divisor and session.use_strict_mode, and returns them as an associative array.

To view the result in a human-readable format use:

  1. // get default settings
  2. print_r('<pre>');
  3. print_r($session->get_settings());
  4.  
  5. // would output something similar to (depending on your actual settings)
  6. // Array
  7. // (
  8. //     [session.gc_maxlifetime] => 1440 seconds (24 minutes)
  9. //     [session.gc_probability] => 1
  10. //     [session.gc_divisor] => 1000
  11. //     [probability] => 0.1%    // <- this is computed from the values above
  12. //     [session.use_strict_mode] => 1
  13. // )
Tags
return:   Returns the values of session.gc_maxlifetime, session.gc_probability, session.gc_divisor and session.use_strict_mode, as an associative array.
since:   1.0.8
top

method regenerate_id()

void regenerate_id ()

Regenerates the session id.

Call this method whenever you do a privilege change, in order to prevent session hijacking!

  1. // regenerate the session's ID
  2. $session->regenerate_id();
top

method set_flashdata()

void set_flashdata ( string $name , string $value )

Sets a flash data session variable which will only be available for the next server request and which will be automatically deleted afterwards.

Typically used for informational or status messages (for example: "data has been successfully updated").

  1. // set "myvar" which will only be available
  2. // for the next server request and will be
  3. // automatically deleted afterwards
  4. $session->set_flashdata('myvar''myval');

"Flash data" session variables can be retrieved like any other session variable:

  1. if (isset($_SESSION['myvar'])) {
  2.     // do something here but remember that the
  3.     // flash data session variable is available
  4.     // for a single server request after it has
  5.     // been set!
  6. }
Arguments
string $name The name of the session variable.
string $value The value of the session variable.
top

method stop()

void stop ()

Deletes all data related to the session.

This method runs the garbage collector respecting your environment's garbage collector-related properties. Read here for more information

  1. // end current session
  2. $session->stop();
Tags
since:   1.0.1
top