Session Class

The session class allows you to maintain state for your application in the stateless environment of the web. It allows you to store variables on the server using a variety of storage solutions, and recall these variables on the next page request.

Manual loading

For most cases, it is sufficient to configure the desired driver, and use the methods documented on the usage page. However, there are situations where you would like more control over the way sessions behave. You might want to use a different session driver than is configured in the session configuration file. Or you have a need for multiple drivers concurrently. This is where the forge method comes in.

The forge method returns an instance of the session class, using the driver defined in the configuration file or via the parameter. You can use the methods documented on the usage page on the object returned, using dynamic calls.

forge($config = array())

The forge method allows you to manually instantiate a session driver.

Static Yes
Parameters
Param Default Description
$config optional You can select the driver of your choice by simply passing the name of the driver to the forge method. If you require more custom configuration, define a $config array, using the parameters documented on the configuration page. Configuration settings you pass here will override the ones defined in the configuration file.
Returns object - The instantiated session object.
Example
// instantiate a database session
$session = Session::forge('db');

// get the counter from the session
$counter = $session->get('counter');

// if not present, set a default
if ($counter === false)
{
	$counter = 0;
}

// write the counter back
$session->set('counter', $counter);

// no need to explicitly write, Fuel will take care of that...

// you can also load a driver with settings that will override the defaults in the config file
$session = Session::forge( array('driver' => 'memcached', 'expiration_time' => 3600, 'memcached' = array('cookie_name' => 'appcookie')) );

Please note: when you want to use multiple session drivers at the same time, the cookie_name for each of these driver instances must be unique. If you attempt to load a driver using a cookie_name that is already in use, and the instance using it uses the same driver as you are trying to load, that instance is reused. If the instance is using a different driver, an exception is thrown.

rotate()

The rotate method allows you to manually force a rotation of the session id. You can use this as an extra security measure, for example when the security level of the current user is modified.

Static No
Parameters None
Returns void
Example
// instantiate a database session
$session = Session::forge('db');

// force a rotation of the session id
$session->rotate();

get_config()

The get_config method allows retrieve a session driver configuration item.

Static No
Parameters
Param Default Description
$name required Name of the session configuration variable.
Returns mixed, the value requested, or null of the requested variable does not exist.
Example
// instantiate a database session
$session = Session::forge('db');

// get the defined session cookie name
$cookiename = $session->get_config('cookie_name');

set_config()

The set_config method allows alter a session driver configuration item at runtime.

Static No
Parameters
Param Default Description
$name required Name of the session configuration variable.
Returns void
Example
// instantiate a database session
$session = Session::forge('db');

// set the expiration time for this session  to 2 hours
$session->set_config('expiration_time', 7200);

Using sessions with Flash

One of the problems with using Flash objects in websites, is that when they interact with your web application, they don't send the cookies back that have been stored in the browser. Due to this problem, it is difficult to make them aware of the session state of the application.

To solve this problem, the Session class allows you to pass the cookie to the application using a POST variable. You can set the name of the variable using the configuration setting 'post_cookie_name'. If the Session class finds a $_POST variable with this name, it will assume it contains the session cookie, and will not use the session cookie. This allows you to copy the contents of the session cookie client-side into the POST variable using a bit of javascript.

When you use a Flash based uploader. you will have to set the match_ua setting to false. You have to do this because Flash uses a different User Agent which will prevent the Session class to correctly identify the users session.

// function to get the session cookie
// you can use or own, or use the one your favorite javascript framework provides
function getCookie(c_name)
{
	if (document.cookie.length > 0)
	{
		c_start = document.cookie.indexOf(c_name + "=");

		if (c_start != -1)
		{
			c_start = c_start + c_name.length + 1;
			c_end = document.cookie.indexOf(";", c_start);
			if (c_end == -1) c_end = document.cookie.length;
			return unescape(document.cookie.substring(c_start, c_end));
		}
	}

	return "";
}

// we're using jquery and uploadify in this example, and we're passing
// the fuel cookie (called 'fuelcid' here) in the formData as 'fuelcid'

// Note: when generating this code, don't hardcode the cookie name, but
// instead get the cookie name from the session configuration file.

// Note:: check the "sessions without cookies" section below if you
// don't have a cookie available to pass the session id back

// ( parameters are related to Uploadify Version 3.2 )

$(function()
{
	$('#custom_file_upload').uploadify(
	{
		'swf'            : '/uploadify/uploadify.swf',
		'uploader'       : '/uploadify/uploadify.php',
		'multi'          : true,
		'auto'           : true,
		'fileTypeExts'   : '*.jpg;*.gif;*.png',
		'fileTypeDesc'   : 'Image Files (.JPG, .GIF, .PNG)',
		'queueID'        : 'custom-queue',
		'queueSizeLimit' : 3,
		'removeCompleted': false,
		'formData'       : {'fuelcid': getCookie('fuelcid')},
		'onSelect'       : function(file)
		{
			alert('The file ' + file.name + ' was added to the queue.');
		},
		'onQueueComplete' : function(queueData)
		{
			alert(queueData.uploadsSuccessful + ' files were successfully uploaded.');
		}
	});
}

Concurrency

When talking about sessions, session cookies, and their behaviour, it is important to understand how they work and what the possibilities and limitations are.

This is especially true when it comes to concurrency. For web-based application, you will have concurrency if you use multiple asynchronous ajax calls on your webpages, or if you allow a browser to have multiple windows open to the same application (which, lets face it, is something you can't prevent).

Something else you need to know is that by default, the session class will rotate (or regenerate) the session id on a regular basis, to prevent session hijacking due to session id fixation (someone stealing your session cookie and use it to take over your session). You can control the rotation time using a configuration setting, or even disable it, but from a security point of view that is a bad idea. Take these two together, and you have a potential disaster on your hands!

An illustration:
- you request a page, the session cookie containing ID-A is sent to the server.
- your page sends two ajax requests. the session cookie containing ID-A is again sent to the server with each request.
- ajax request 1 finishes, and rotates the ID. A cookie with ID-B is sent to the browser.
- now ajax request 2 finishes. Because it sent the same cookie, it also decides to rotate, this time to ID-C.
(you will get a different ID, because session IDs are generated using a randomized algorithm)

Now we have a problem. The session class tries to update the stored session with key ID-A to ID-C, but it can't find that session. Remember, it had been updated from ID-A to ID-B by the first ajax call! So it decides the session is invalid, create a new and empty session, and return that cookie to the browser. Now your valid cookie is overwritten by the new and empty session cookie. Result: you have lost the session.

This is an issue that most frameworks have not solved. Enter Fuel!

Fuel's session class contains two mechanisms to detect and mitigate this problem. Every session key store contains two session IDs: the current ID and the previous ID. If a request comes in just after the session id has been rotated, the correct session can be located using the previous session id stored in the key store. And it case of a session id mismatch which could not be recovered using the previous id, no updated cookie will be sent back to the browser. The result is that you lose the session data of that request, but you don't lose the session itself.

Sessions without cookies

After a change to the session data, the Session class will always generate a session cookie, and send it to the client in the HTTP response header. However, there are situations where is it undesireable, of even impossible, to use cookies. For example simply because the client does not support them.

In these cases, there are alternative ways to pass a Session ID back to the application on a request from the client:

You can use Session::key() to retrieve the current session id, so you can pass it to the client in the response, instead of using a cookie. If you have configured encryption in your session configuration, you need to encrypt the id:

// fetch the session ID and encrypt it
$session_id = \Crypt::encode(\Session::key());