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.1.0 (last revision: September 08, 2024)
See CHANGELOG
License:
Copyright:
- © 2006 - 2024 Stefan Gabos
Implements interfaces:
- SessionHandlerInterface (internal interface)
Class methods
constructor __construct()
void
__construct
(
resource
&$link
,
string
$security_code
,
[
integer
$session_lifetime
=
0
]
,
[
boolean
$lock_to_user_agent
=
true
]
,
[
boolean|callable
$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()
// first, connect to a database containing the sessions table, either via PDO or using mysqli_connect
// include the class
// (you don't need this if you are using Composer)
require 'path/to/Zebra_Session.php';
// start the session
// where $link is a connection link returned by mysqli_connect or a PDO instance
The following configuration options are set by the library when instantiated:
// only when over HTTPS
ini_set('session.cookie_secure', 1);
// don't expose the cookie to client side scripting making it harder for an attacker to hijack the session ID
ini_set('session.cookie_httponly', 1);
// make sure that PHP only uses cookies for sessions and disallow session ID passing as a GET parameter
ini_set('session.use_only_cookies', 1);
The following configuration options are recommended to be set before instantiating this library:
// disallows supplying session IDs via `session_id('ID HERE')
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:
// takes the domain and removes the subdomain
// blog.domain.com becoming .domain.com
'session.cookie_domain',
substr($_SERVER['SERVER_NAME'], strpos($_SERVER['SERVER_NAME'], '.'))
);
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: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4...
and reloading the page you would have Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4...
So, if the situation asks for this, change this value to false . Default is true . |
boolean|callable |
$lock_to_ip |
(Optional) Whether to restrict the session to the same IP as when the session was first opened. For the actual IP address that is going to be used, the library will use the value of $_SERVER['REMOTE_ADDR'] . If your application is behind a load balancer like an AWS Elastic Load Balancing or a reverse proxy like Varnish, certain request information will be sent using either the standard Forwarded header or the X-Forwarded-* headers. In this case, the REMOTE_ADDR header will likely be the IP address of your reverse proxy while the user's true IP will be stored in a standard Forwarded header or an X-Forwarded-For header. In this case you will need to tell the library which reverse proxy IP addresses to trust and what headers your reverse proxy uses to send information by using a callable value for this argument:
$link,
'someSecur1tyCode!',
0,
false,
// one way of using a callable for this argument
function() {
$ipaddress = '';
// use the header(s) you choose to trust
foreach (['HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED'] as $key) {
// use the first one containing a value
$ipaddress = $tmp;
break;
}
}
return $ipaddress;
}
);
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
// get the number of 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:
// get default settings
// would output something similar to (depending on your actual settings)
// Array
// (
// [session.gc_maxlifetime] => 1440 seconds (24 minutes)
// [session.gc_probability] => 1
// [session.gc_divisor] => 1000
// [probability] => 0.1% // <- this is computed from the values above
// [session.use_strict_mode] => 1
// )
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!
// regenerate the session's 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").
// set "myvar" which will only be available
// for the next server request and will be
// automatically deleted afterwards
"Flash data" session variables can be retrieved like any other session variable:
if (isset($_SESSION['myvar'])) {
// do something here but remember that the
// flash data session variable is available
// for a single server request after it has
// been set!
}
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
// end current session
Tags
top