1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
| <?php
/**
* @package Libraries
* @lastmodif 2009.08.24:03.16PM
* @version 1.0
*/
if( ! class_exists( 'Lib_Session' ) )
{
/**
* This class handle the whole session process. It will creates a new
* session within db or get an existing one using the classic php session
* functionnalities. Moreover, it attempts to prevent session fixation
* by changing the session id twice at every page call.
*/
class Lib_Session
implements Vsf_Singleton_Interface
{
protected static $o_Instance; // Unique instance of the singleton
protected static $o_Model; // The database model instance
const i_LastIdTimeOut = 30; // The last session id validity
// The current session data fields (corresponding to the db fields)
protected static $s_SessionId, $s_LastSessionId, $i_SessionStart,
$i_LastActivity, $s_Userdata;
/**
* The protected constructor for the singleton instance
*/
protected function __construct()
{
session_set_save_handler(
array( & $this, 'open' ),
array( & $this, 'close' ),
array( & $this, 'read' ),
array( & $this, 'write' ),
array( & $this, 'destroy' ),
array( & $this, 'gc' )
);
// We set the values for some configuration options
ini_set( 'session.name', 'sid' );
ini_set( 'session.gc_probability', 10 );
ini_set( 'session.gc_divisor', 100 );
ini_set( 'session.gc_maxlifetime', 3600 );
session_start();
session_regenerate_id(); // Attempt to prevent session fixation
}
/**
* Return and build if necessary the singleton instance of this class
*
* @return Lib_Session
*/
public static function GetInstance()
{
// If there is no instance of the Lib_Session ...
if( ! self::$o_Instance instanceof self )
self::$o_Instance = new self; // ... we create one.
// We return the Lib_Session instance
return self::$o_Instance;
}
/**
* Open function, this works like a constructor and is executed when the
* session is being opened. The open function expects two parameters,
* where the first is the save path and the second is the session name.
*
* @param string $s_Path The session path
* @param string $s_Name The session name
* @return bool (always true)
*/
public static function Open( $s_Path, $s_Name )
{
self::$o_Model = new Model_Session;
return true;
}
/**
* Close function, this works like a destructor and is executed when the
* session operation is done.
*
* @return bool (always true)
*/
public static function Close()
{
@mysql_close();
return true;
}
/**
* Read function must return string value always to make save handler
* work as expected. Return empty string if there is no data to read.
* Return values from other handlers are converted to boolean
* expression. TRUE for success, FALSE for failure.
*
* @param string $s_SessionId The unique session id
* @return string The userdata to store with the $_SESSION superglobal
*/
public static function Read( $s_SessionId )
{
// Try to get the session data informations from database
$h_Where = array( 'session_id' => $s_SessionId );
$a_Model = self::$o_Model->Select( NULL, $h_Where, NULL, 0, 1 );
// There is a corresponding session id into db
if( count( $a_Model ) )
{
// We get the content of $a_Model[0]
$h_Model = array_shift( $a_Model );
// The we set the session corresponding properties ...
self::$s_SessionId = $h_Model['session_id'];
self::$s_LastSessionId = $h_Model['last_session_id'];
self::$i_SessionStart = $h_Model['session_start'];
self::$i_LastActivity = $h_Model['last_activity'];
self::$s_Userdata = $h_Model['userdata'];
// ... and return the corresponding userdata
return self::$s_Userdata;
}
else // There is no corresponding session id into db
{
// Check if there is an old session id into db
$h_Where = array( 'last_session_id' => $s_SessionId );
$a_Model = self::$o_Model->Select( NULL, $h_Where, NULL, 0, 1 );
// There is a corresponding old session id into db
if( count( $a_Model ) )
{
// We get the content of $a_Model[0]
$h_Model = array_shift( $a_Model );
// We must check whether the last session id is still valid
$i_LastValidTime = $h_Model['last_activity'] + self::i_LastIdTimeOut;
if( $i_LastValidTime > time() )
{
// The we set the session corresponding properties ...
self::$s_SessionId = $h_Model['session_id'];
self::$s_LastSessionId = $h_Model['last_session_id'];
self::$i_SessionStart = $h_Model['session_start'];
self::$i_LastActivity = $h_Model['last_activity'];
self::$s_Userdata = $h_Model['userdata'];
// ... and return the corresponding userdata
return self::$s_Userdata;
}
}
}
return '';
}
/**
* The "write" handler is not executed until after the output stream is
* closed. Thus, output from debugging statements in the "write" handler
* will never be seen in the browser. If debugging output is necessary,
* it is suggested that the debug output be written to a file instead.
*
* @param string $s_SessionId The unique session id
* @param string $h_SessionData The corresponding session data
* @return bool Whether the write request succeeded or not
*/
public function Write( $s_SessionId, $h_SessionData )
{
// Is a session model registered in database ?
if( ! isset( self::$s_SessionId ) )
{
// NO: We creates new session data
$h_Model = array( 'session_id' => $s_SessionId,
'last_session_id' => self::$s_SessionId,
'session_start' => time(),
'last_activity' => time(),
'userdata' => $h_SessionData );
return self::$o_Model->Insert( $h_Model );
}
else
{
// YES: We creates a new session id ...
$h_Model = array( 'session_id' => $s_SessionId,
'last_session_id' => self::$s_SessionId,
'session_start' => self::$i_SessionStart,
'last_activity' => time(),
'userdata' => $h_SessionData );
// ... and update the session data !
$h_Where = array( 'session_id' => self::$s_SessionId );
return self::$o_Model->Update( $h_Model, $h_Where );
}
}
/**
* The destroy handler, this is executed when a session is destroyed
* with session_destroy() and takes the session id as its only parameter
*
* @param string $s_SessionId The unique session id
* @return bool Whether the delete request succeeded or not
*/
public function Destroy( $s_SessionId )
{
// Check whether session is registered in db ?
if( isset( self::$s_SessionId ) )
{
// Where session_start < actual time - session maxlifetime
$h_Where = array( 'field' => 'session_id',
'operator' => '=',
'value' => $s_SessionId
);
// Delete the expired sessions
self::$o_Model->Delete( array( 0 => $h_Where ) );
}
return true;
}
/**
* The garbage collector, this is executed when the session garbage
* collector is executed and takes the max session lifetime as its
* only parameter.
*
* @param string $i_MaxLifeTime The maximum lifetime for a session
* @return bool (always true)
*/
public function Gc( $i_MaxLifeTime )
{
// Where session_start < actual time - session maxlifetime
$h_Where = array( 'field' => 'session_start',
'operator' => '<',
'value' => time() - $i_MaxLifeTime
);
// Delete the expired sessions
self::$o_Model->Delete( array( 0 => $h_Where ) );
return true;
}
}
} |
Partager