Part of the EllisLab Network
x
 
Create New Page
 View Previous Changes    ( Last updated by ReGeDa )

Secure Native Session

What’s new?

- 2 way for store your session information: private & public zone.
- native php session used

Config
sess_expiration - 0 -> never expire (2 years), -1 -> browser session, greater 0 -> your special expire
sess_revalidate_id - TRUE or FALSE
Warning!
public data has never expire setting
It’s works with database store enabled only!

SQL

create table ci_sessions (
session_id varchar(40) default '0' not null primary key,
ip_address varchar(16) default '0' not null,
user_agent varchar(50not null,
last_activity integer default 0 not null,
private 
text default '' not null
); 

Reference

function system($item) // get CI standart session information
function _sess_regenerate_allow() // you can override it for your regenerate allow
function private_data($item// get your private item
function public_data($item// get your public item
function set_private_data($newdata,$newval// set your private item with arguments as CI set_userdata
function set_public_data($newdata,$newval// set your public item with arguments as CI set_userdata
function unset_private_data($items// delete items (array) from private data
function unset_public_data($items// delete items (array) from public data 

CI standart

function set_flashdata(...)
function 
flashdata(...) 

How to install
1. replace CI session class & edit your code with special Secure Native Session reference
2. rename this name class & use with happy


P.S.
not include GMT time parameter, current ‘local’
Discuss - http://codeigniter.com/forums/viewthread/86472/

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class 
CI_Session {
    
    
var $CI;
    var 
$now;
    var 
$userdata = array();
    var 
$time_to_update 300;
    var 
$gc_probability    5;
    var 
$flashdata_key 'flash';
    var 
$sess_cookie 'ci_session';
    var 
$session_length 7200;
    var 
$session_table 'ci_session';
    var 
$session_id;
    
    
    
/**
        Session Constructor
    */
    
function CI_Session() {
        $this
->CI =& get_instance();
        
log_message('debug'"Native Session Class Initialized");
        
$this->sess_run();
    
}
    
    
/**
        get 2 years in seconds
    */
    
function _get_2years_seconds() {
        
return 60*60*24*365*2;
    
}
    
    
/**
        Run the session routines
    */
    
function sess_run() {        
        
// session start
        
session_start();
        
        
// time to update
        
if (is_numeric($this->CI->config->item('sess_time_to_update')))
            
$this->time_to_update $this->CI->config->item('sess_time_to_update');
        
        
// now - only 'local'
        
$this->now time();
        
        
// session life
        
$expiration $this->CI->config->item('sess_expiration');
        if (
is_numeric($expiration)) {
            
if ($expiration 0// user defined
                
$this->sess_length $this->CI->config->item('sess_expiration');
            else if (
$expiration 0// no save
                
$this->sess_length 0;
            else 
// save session
                
$this->sess_length $this->_get_2years_seconds();
        
}
        
        
// Set the cookie name
        
if ($this->CI->config->item('sess_cookie_name') != FALSE)
            
$this->sess_cookie $this->CI->config->item('cookie_prefix').$this->CI->config->item('sess_cookie_name');
        
        
// database always is need
        
$this->session_table $this->CI->config->item('sess_table_name');
        
$this->CI->load->database();
        
        
// Fetch the current session
        
if (! $this->sess_read()) 
            
$this->sess_create();
        else if ((
$this->userdata['last_activity'$this->time_to_update) < $this->now)
            
$this->sess_update();
            
        
// Fetch public zone
        
$this->userdata['public'$this->_unserialize($this->CI->input->cookie($this->sess_cookie));
            
        
// Delete expired sessions if necessary
        
$this->sess_gc();
        
        
// Delete 'old' flashdata (from last request)
           
$this->_flashdata_sweep();
        
        
// Mark all new flashdata as old (data will be deleted before next request)
           
$this->_flashdata_mark();
    
}
    
    
/**
        Remove from the DB
    */
    
function _sess_delete() {        
        $this
->CI->db->where('session_id'$this->session_id);
        
$this->CI->db->delete($this->session_table);
    
}
    
    
/**
        Fetch the current session data if it exists
    */
    
function sess_read() {    
        
// fetch session hash        
        
$this->session_id session_id();
        
        
// read from database
        
$this->CI->db->where('session_id'$this->session_id);
        
$query $this->CI->db->get($this->session_table);
        
// has session id
        
if ($query->num_rows()) {
            $session 
$query->row_array();
            
            
// Is the session current?
            
if ($this->sess_length && ($session['last_activity'$this->sess_length) < $this->now{
                $this
->_sess_delete();
                return 
false;
            
}
            
// Does the IP Match?
            
if ($this->CI->config->item('sess_match_ip') && $session['ip_address'!= $this->CI->input->ip_address())
                return 
false;
                
            
// Does the User Agent Match?
            
if ($this->CI->config->item('sess_match_useragent') && trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 050)))
                return 
false;
                
            
// Fetch security data            
            
$session['private'$this->_unserialize($session['private']);
                
            
// Session is valid!
            
$this->userdata $session;
            unset(
$session);
        
            return 
true;
        
}
        
else 
            return 
false;
    
}
    
    
/**
        Set cookie
    */
    
function _set_cookie($key,$value,$lifetime{
        setcookie
($key,$value,$lifetime,$this->CI->config->item('cookie_path'),$this->CI->config->item('cookie_domain'));
    
}
    
    
/**
        Write the session cookie
    */
    
function sess_write($saved false$only_private true{    
        
// set cookie
        
$this->_set_cookie(session_name(),$this->session_id,$this->sess_length?$this->sess_length+time():0);
        
        
// save zones
        
if ($saved{        
            
// private zone
            
if ($only_private)
                
$this->CI->db->update($this->session_table,$this->_serialize_private(),
                    array(
'session_id' => $this->session_id));
            else 
// public zone
                
$this->_set_cookie($this->sess_cookie,serialize($this->userdata['public']),$this->_get_2years_seconds()+time());
        
}
    }
    
    
/**
        Create a new session
    */
    
function sess_create() {
        
        $this
->userdata = array(
            
'session_id'     => $this->session_id,
            
'ip_address'     => $this->CI->input->ip_address(),
            
'user_agent'     => substr($this->CI->input->user_agent(), 050),
            
'last_activity'    => $this->now
        
);
        
        
// save in the DB
        
$this->CI->db->query($this->CI->db->insert_string($this->session_table$this->userdata));
        
        
// create extra fields
        
$this->userdata['private'= array();
        
        
// session write
        
$this->sess_write();
    
}
    
    
/**
        class hook for override
        fetch regenerate allow flag 
    */
    
function _sess_regenerate_allow() {
        
return true;
    
}
    
    
/**
        Update an existing sessio
    */
    
function sess_update() {
        $oldssid 
$this->session_id;
        
        
$update['last_activity'$this->now;
        
        
// regenerate
        
if ($this->CI->config->item('sess_revalidate_id') && $this->_sess_regenerate_allow()) {
            session_regenerate_id
();
            
// save new session id
            
$this->userdata['session_id'$update['session_id'$this->session_id session_id();
        
}
        
        
// update DB
        
$this->CI->db->query($this->CI->db->update_string($this->session_table$update, array('session_id' => $oldssid)));
        
        
// update data
        
$this->userdata['last_activity'$this->now;
                
        
// session write
        
$this->sess_write();
    
}
    
    
/**
        Garbage collection
    */
    
function sess_gc() {
        
if ($this->sess_length == 0) return;
        
// garbage go!    
        
srand(time());
        if ((
rand() % 100) < $this->gc_probability)    {
            $expire 
$this->now $this->sess_length;
            
            
$this->CI->db->where("last_activity < {$expire}");
            
$this->CI->db->delete($this->session_table);

            
log_message('debug''Session garbage collection performed.');
        
}
    }
    
    
/**
        Destroy the current session
    */
    
function sess_destroy() {
        $this
->_sess_delete();
    
        
// Unset all of the session variables.
        
$_SESSION = array();

        
// If it's desired to kill the session, also delete the session cookie.
        // Note: This will destroy the session, and not just the session data!
        
if (isset($_COOKIE[session_name()]))
            
$this->_set_cookie(session_name(),'',$this->now 31500000);

        
// Finally, destroy the session.
        
session_destroy();
    
}
    
    
/**
        Fetch a system value
    */
    
function system($item) {
        
return $this->userdata[$item];
    
}
    
    
/**
        Fetch a specific value
    */
    
function _userdata($item,$type{
        
return (! isset($this->userdata[$type][$item]))?false:$this->userdata[$type][$item];
    
}
    
    
/**
        Fetch a public value
    */
    
function public_data($item{
        
return $this->_userdata($item,'public');
    
}
    
    
/**
        Fetch a private value
    */
    
function private_data($item{
        
return $this->_userdata($item,'private');
    
}
    
    
/**
        Add or change a data
    */
    
function _set_userdata($type$newdata$newval{
        
if (is_string($newdata))
            
$newdata = array($newdata => $newval);
    
        if (
count($newdata) > 0{
            
foreach ($newdata as $key => $val)
                
$this->userdata[$type][$key] $val;                
            
$this->sess_write(true,$type == 'private');
        
}
    }
    
    
/**
        Remove a data
    */
    
function _unset_userdata($type,$data{
        
if (is_string($data))
            
$data = array($data);
        if (
count($data) > 0{
            
foreach ($data as $val)
                unset(
$this->userdata[$type][$val]);            
            
$this->sess_write(true,$type == 'private');
        
}
    }
    
    
/**
        Add or change a public data
    */
    
function set_public_data($newdata = array(), $newval ''{
        $this
->_set_userdata('public',$newdata,$newval);
    
}
    
    
/**
        Add or change a private data
    */
    
function set_private_data($newdata = array(), $newval ''{
        $this
->_set_userdata('private',$newdata,$newval);
    
}
    
    
/**
        Remove a private data
    */
    
function unset_private_data($data = array()) {
        $this
->_unset_userdata('private',$data);
    
}
    
    
/**
        Remove a public data
    */
    
function unset_public_data($data = array()) {
        $this
->_unset_userdata('public',$data);
    
}
    
    
/**
        Add or change flashdata, only available
    */
    
function set_flashdata($newdata = array(), $newval ''{
        
if (is_string($newdata))
            
$newdata = array($newdata => $newval);

        if (
count($newdata) > 0{
            $flashdata 
= array();
            foreach (
$newdata as $key => $val)
                
$flashdata[$this->flashdata_key.':new:'.$key] $val;            
            
$this->set_public_data($flashdata);
        
}
    }
    
    
/**
        Fetch a specific flashdata item from the session array
    */
    
function flashdata($key{
        
return $this->public_data($this->flashdata_key.':old:'.$key);
    
}
    
    
/**
        Identifies flashdata as 'old' for removal
    */
    
function _flashdata_mark() {
        
foreach ($this->userdata['public'as $name => $value{
            $parts 
explode(':new:'$name);
            if (
is_array($parts) && count($parts) === 2{
                $new_name 
$this->flashdata_key.':old:'.$parts[1];
                
$this->userdata['public'][$new_name] $value;
                unset(
$this->userdata['public'][$name]);
            
}
        }
        $this
->sess_write(true,false);
    
}

    
/**
        Removes all flashdata marked as 'old'
    */
    
function _flashdata_sweep() {
        
foreach ($this->userdata['public'as $key => $value)
            if (
strpos($key':old:'))                
                unset(
$this->userdata['public'][$key]);
    
}
    
    
/**
        unserialize string
    */
    
function _unserialize($str{
        
if (is_array($data = @unserialize($this->_strip_slashes($str)))) 
            return 
$data;
        else
            return array();
    
}
    
    
/**
        Strip slashes
    */
    
function _strip_slashes($vals{
        
if (is_array($vals))
             foreach (
$vals as $key=>$val)
                 
$vals[$key] $this->_strip_slashes($val);
         else
             
$vals stripslashes($vals);
         return 
$vals;
    
}
    
    
/**
        Get the session serialize security
    */
    
function _serialize_private() {
        
return array('private' => serialize($this->userdata['private']));
    
}