PHP Programming/Sessions

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Sessions allow the PHP script to store data on the web server that can be later used, even between requests to different PHP pages. Every session has a different identifier, which is sent to the client's browser as a cookie or as a $_GET variable. Sessions end when the user closes the browser, or when the web server deletes the session information, or when the programmer explicitly destroys the session. In PHP it's usually called PHPSESSID. Sessions are very useful to protect the data that the user wouldn't be able to read or write, especially when the PHP developer doesn't want to give out information in the cookies as they are easily readable. Sessions can be controlled by the $_SESSION superglobal. Data stored in this array is persistent throughout the session. It is a simple array. Sessions are much easier to use than cookies, which helps PHP developers a lot. Mostly, sessions are used for user logins, shopping carts and other additions needed to keep browsing smooth. PHP script can easily control the session's cookie which is being sent and control the whole session data. Sessions are always stored in a unique filename, either in a temporary folder or in a specific folder, if a script instructs to do so.

Using Sessions[edit | edit source]

At the top of each PHP script that will be part of the current session there must be the function session_start(). It must be before the first output (echo or others) or it will result in an error "Headers already sent out".

 session_start();

This function will do these actions:

  1. it will check the _COOKIE or _GET data, if it is given
  2. if the session file doesn't exist in the session.save_path location, it will:
    1. generate a new Unique Identifier, and
    2. create a new file based on that Identifier, and
    3. send a cookie to the client's browser
  3. if it does exist, the PHP script will attempt to store the file's data into _SESSION variable for further use

Now, you can simply set variables in 2 different ways, the default method:

 $_SESSION['example'] = "Test";

Or the deprecated method:

 $example="Test";
 session_register($example);

Both of the above statements will register the session variable $_SESSION['example'] as "Test". The deprecated method should not be used, it is only listed because you can still see it in scripts written by programmers that don't know the new one. The default method is preferred.

Session Configuration Options[edit | edit source]

PHP sessions are easy to control and can be made even more secure or less secure with small factors. Here are runtime options that can be easily changed using php_ini() function:

Name Default Changeable
session.save_path "/tmp" PHP_INI_ALL
session.name "PHPSESSID" PHP_INI_ALL
session.save_handler "files" PHP_INI_ALL
session.auto_start "0" PHP_INI_ALL
session.gc_probability "1" PHP_INI_ALL
session.gc_divisor "100" PHP_INI_ALL
session.gc_maxlifetime "1440" PHP_INI_ALL
session.serialize_handler "php" PHP_INI_ALL
session.cookie_lifetime "0" PHP_INI_ALL
session.cookie_path "/" PHP_INI_ALL
session.cookie_domain "" PHP_INI_ALL
session.cookie_secure "" PHP_INI_ALL
session.use_cookies "1" PHP_INI_ALL
session.use_only_cookies "0" PHP_INI_ALL
session.referer_check "" PHP_INI_ALL
session.entropy_file "" PHP_INI_ALL
session.entropy_length "0" PHP_INI_ALL
session.cache_limiter "nocache" PHP_INI_ALL
session.cache_expire "180" PHP_INI_ALL
session.use_trans_sid "0" PHP_INI_SYSTEM/PHP_INI_PERDIR
session.bug_compat_42 "1" PHP_INI_ALL
session.bug_compat_warn "1" PHP_INI_ALL
session.hash_function "0" PHP_INI_ALL
session.hash_bits_per_character "4" PHP_INI_ALL
url_rewriter.tags "a=href,area=href,frame=src,input=src,form=fakeentry" PHP_INI_ALL

A simple example of this use would be this code:

 //Setting The Session Saving path to "sessions", '''must be protected from reading'''
 session_save_path("sessions"); // This function is an alternative to ini_set("session.save_path","sessions");
 //Session Cookie's Lifetime ( not effective, but use! )
 ini_set("session.cookie_lifetime",time()+60*60*24*500);
 //Change the Session Name from PHPSESSID to SessionID
 session_name("SessionID");
 //Start The session
 session_start();
 //Set a session cookie ( Required for some browsers, as settings that had been done before are not very effective 
 setcookie(session_name(), session_id(), time()+3600*24*365, "/");

This example simply sets the cookie for the next year.

Ending a Session[edit | edit source]

When user clicks "Logout", or "Sign Off", you would usually want to destroy all the login data so nobody could have access to it anymore. The session file will be simply deleted as well as the cookie to be unset by:

 session_destroy();

Using Session Data of Other Types[edit | edit source]

Simple data such as integers, strings, and arrays can easily be stored in the $_SESSION superglobal array and be passed from page to page. But problems occur when trying to store the state of an object by assignment. Object state can be stored in a session by using the serialize() function. serialize() will write the objects data into an array which then can be stored in a $_SESSION supergloblal. unserialize() can be used to restore the state of an object before trying to access the object in a page that is part of the current session. If objects are to be used across multiple page accesses during a session, the object definition must be defined before calling unserialize(). Other issues may arise when serializing and unserializing objects.

Avoiding Session Fixation[edit | edit source]

Session fixation describes an attack vector in which a malicious third-party sets (i.e. fixes) the session identifier (SID) of a user, and is thus able to access that user's session. In the base-level implementation of sessions, as described above, this is a very real vulnerability, and every PHP program that uses sessions for anything at all sensitive should take steps to remedy it. The following, in order of how widely applicable they are, are the measures to take to prevent session fixation:

  1. Do not use GET or POST variables to store the session ID (under most PHP configurations, a cookie is used to store the SID, and so the programmer doesn't need to do anything to implement this);
  2. Regenerate the SID on each user request (using session_regenerate_id() at the beginning of the session);
  3. Use session time-outs: for each user request, store the current timestamp, and on the next request check that the timeout interval has not passed;
  4. Provide a logout function;
  5. Check the 'browser fingerprint' on each request. This is a hash, stored in a $_SESSION variable, comprising some combination of the user-agent header, client IP address, a salt value, and/or other information. See below for more discussion of the details of this; it is thought by some to be nothing more than 'security through obscurity'. [TODO]
  6. Check referrer: this does not work for all systems, but if you know that users of your site must be coming from some known domain you can discard sessions tied to users from elsewhere. It relies on the user agent providing the referrer header, which should not be assumed.
This example code addresses all of the above points save the referrer check.
$timeout = 3 * 60; // 3 minutes
$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']);
session_start();
if ( (isset($_SESSION['last_active']) && (time() > ($_SESSION['last_active']+$timeout)))
     || (isset($_SESSION['fingerprint']) && $_SESSION['fingerprint']!=$fingerprint)
     || isset($_GET['logout']) ) {
    do_logout();
}
session_regenerate_id(); 
$_SESSION['last_active'] = time();
$_SESSION['fingerprint'] = $fingerprint;
The do_logout() function destroys the session data and unsets the session cookie.