Thursday, August 16, 2007

This is one of the works for the new Sym.posium project. My first idea was that I'd need store more information about the user in the session (statistics, authentification, session preferences of the user, ....). My first problem is that, my RsAuth library (Really Simple Authentification) store username logged and other authentification info in the cookies, this is unsecure because somebody can change the cookie data and hack the authentification.

CodeIgniter has the option for encrypt the cookie data, but, anyway somebody can uncrypt the data (knowing the encryptation key or brute force), so I needed the same session class logic but not store the sensitive data in the cookie and store in the database. Lukely CodeIgniter also has an option for save some information of the sessions in a table in the database (session_id, last_activity,....) but the session variables is stored in the cookie and it does not in the database.

This solution (that I think), is not good, because, the sensitive data is exposed in the cookie, and the cookie data (if is big) is transfered in all communication server-client, so I am loosing bandwidth. Also, because a stupid bug in IE 5.5 cookies, CodeIgniter does not implement non persistent cookies (deleted when the browser close), if another user use your computer before the session end, although you have closed the page tab or the browser, the new user can use the same session cookie, and gets your authentification, and this is not good.

CodeIgniter has the possibility of extend the core classes, for customize your code. So this is my session class extension for support non-persistent cookies and session variables stored in database.

Download

Download MY_Session.php

Installation

1. You need configure your sessions for to use the database. In config.php:

$config['sess_encrypt_cookie'] = TRUE;
$config['sess_use_database'] = TRUE;
$config['sess_table_name'] = 'sessions';
$config['sess_match_ip'] = TRUE;
$config['sess_match_useragent'] = TRUE;
$config['sess_cookie_isnonpersistent'] = TRUE; //Cookie hack

This simple configuration sets the cookie encryption, the database use, and we add some security settings like match_ip and match_useragent. The latest setting is for nonpersistent cookies support, if is FALSE, cookies has the normal behaviour with session expiration time, and if is TRUE, cookies is deleted when the browser is closed, but also, session is expired when the session time is expired.

2. Check if the Class Extension prefix is MY_ , if not, rename MY_Session.php file to the correct name. In config.php:

$config['subclass_prefix'] = 'MY_';

3. You need declare sessions table of a new way setting the new user_data field:

CREATE TABLE sessions (
session_id varchar(40) collate utf8_bin NOT NULL default '0',
ip_address varchar(16) collate utf8_bin NOT NULL default '0',
user_agent varchar(50) collate utf8_bin NOT NULL default '',
last_activity int(10) unsigned NOT NULL default '0',
user_data text collate utf8_bin,
PRIMARY KEY (session_id)
);

4. Finally store your MY_Session.php file in your application/libraries folder.

This extension overwrite the userdata method. This method gets at first the value if exists in database session info, and if it is not found, then tries in session cookie. Also the method set_userdata writes in database session info, and if you need write in cookies, then use the new method set_userdata_cookies. The code of the file is simple and self documented.

Labels: ,

1 comments, Post a CommentPosted by posted by SeViR @ 9:07 AM
1 Comments
Dec 25, 2007 6:44:00 PM, Anonymous Edemilson Lima - pulstar at gmail dot com said:
I liked very much your implementation to save session vars in the database. In fact, it was my first idea too. But isn't the PHP native session engine made in compiled C code faster than any implementation made in PHP code?

My main concern is: how much these implementations using cookies or databases are better to save server resources? How does PHP native session behave when we have thousands of simultaneous users?

I think you could made it more flexible using $this->CI->config->item('sess_table_name') to get the name of the session database from the config file.  
Links to this post
This design is under copyright of SeViR CW © 2007