123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- <?php
- /**
- * Part of the Fuel framework.
- *
- * @package Fuel
- * @version 1.5
- * @author Fuel Development Team
- * @license MIT License
- * @copyright 2010 - 2013 Fuel Development Team
- * @link http://fuelphp.com
- */
- namespace Fuel\Core;
- // --------------------------------------------------------------------
- class Session_Redis extends \Session_Driver
- {
- /**
- * array of driver config defaults
- */
- protected static $_defaults = array(
- 'cookie_name' => 'fuelrid', // name of the session cookie for redis based sessions
- 'database' => 'default' // name of the redis database to use (as configured in config/db.php)
- );
- /*
- * @var storage for the redis object
- */
- protected $redis = false;
- // --------------------------------------------------------------------
- public function __construct($config = array())
- {
- // merge the driver config with the global config
- $this->config = array_merge($config, is_array($config['redis']) ? $config['redis'] : static::$_defaults);
- $this->config = $this->_validate_config($this->config);
- }
- // --------------------------------------------------------------------
- /**
- * driver initialisation
- *
- * @access public
- * @return void
- */
- public function init()
- {
- // generic driver initialisation
- parent::init();
- if ($this->redis === false)
- {
- // get the redis database instance
- $this->redis = \Redis::instance($this->config['database']);
- }
- }
- // --------------------------------------------------------------------
- /**
- * create a new session
- *
- * @access public
- * @return Fuel\Core\Session_Redis
- */
- public function create()
- {
- // create a new session
- $this->keys['session_id'] = $this->_new_session_id();
- $this->keys['previous_id'] = $this->keys['session_id']; // prevents errors if previous_id has a unique index
- $this->keys['ip_hash'] = md5(\Input::ip().\Input::real_ip());
- $this->keys['user_agent'] = \Input::user_agent();
- $this->keys['created'] = $this->time->get_timestamp();
- $this->keys['updated'] = $this->keys['created'];
- return $this;
- }
- // --------------------------------------------------------------------
- /**
- * read the session
- *
- * @access public
- * @param boolean, set to true if we want to force a new session to be created
- * @return Fuel\Core\Session_Driver
- */
- public function read($force = false)
- {
- // initialize the session
- $this->data = array();
- $this->keys = array();
- $this->flash = array();
- // get the session cookie
- $cookie = $this->_get_cookie();
- // if a cookie was present, find the session record
- if ($cookie and ! $force and isset($cookie[0]))
- {
- // read the session file
- $payload = $this->_read_redis($cookie[0]);
- if ($payload === false)
- {
- // cookie present, but session record missing. force creation of a new session
- return $this->read(true);
- }
- // unpack the payload
- $payload = $this->_unserialize($payload);
- // session referral?
- if (isset($payload['rotated_session_id']))
- {
- $payload = $this->_read_redis($payload['rotated_session_id']);
- if ($payload === false)
- {
- // cookie present, but session record missing. force creation of a new session
- return $this->read(true);
- }
- else
- {
- // update the session
- $this->keys['previous_id'] = $this->keys['session_id'];
- $this->keys['session_id'] = $payload['rotated_session_id'];
- // unpack the payload
- $payload = $this->_unserialize($payload);
- }
- }
- if ( ! isset($payload[0]) or ! is_array($payload[0]))
- {
- // not a valid cookie payload
- }
- elseif ($payload[0]['updated'] + $this->config['expiration_time'] <= $this->time->get_timestamp())
- {
- // session has expired
- }
- elseif ($this->config['match_ip'] and $payload[0]['ip_hash'] !== md5(\Input::ip().\Input::real_ip()))
- {
- // IP address doesn't match
- }
- elseif ($this->config['match_ua'] and $payload[0]['user_agent'] !== \Input::user_agent())
- {
- // user agent doesn't match
- }
- else
- {
- // session is valid, retrieve the rest of the payload
- if (isset($payload[0]) and is_array($payload[0])) $this->keys = $payload[0];
- if (isset($payload[1]) and is_array($payload[1])) $this->data = $payload[1];
- if (isset($payload[2]) and is_array($payload[2])) $this->flash = $payload[2];
- }
- }
- return parent::read();
- }
- // --------------------------------------------------------------------
- /**
- * write the session
- *
- * @access public
- * @return Fuel\Core\Session_Redis
- */
- public function write()
- {
- // do we have something to write?
- if ( ! empty($this->keys) or ! empty($this->data) or ! empty($this->flash))
- {
- parent::write();
- // rotate the session id if needed
- $this->rotate(false);
- // session payload
- $payload = $this->_serialize(array($this->keys, $this->data, $this->flash));
- // create the session file
- $this->_write_redis($this->keys['session_id'], $payload);
- // was the session id rotated?
- if ( isset($this->keys['previous_id']) and $this->keys['previous_id'] != $this->keys['session_id'])
- {
- // point the old session file to the new one, we don't want to lose the session
- $payload = $this->_serialize(array('rotated_session_id' => $this->keys['session_id']));
- $this->_write_redis($this->keys['previous_id'], $payload);
- }
- $this->_set_cookie(array($this->keys['session_id']));
- }
- return $this;
- }
- // --------------------------------------------------------------------
- /**
- * destroy the current session
- *
- * @access public
- * @return Fuel\Core\Session_Redis
- */
- public function destroy()
- {
- // do we have something to destroy?
- if ( ! empty($this->keys))
- {
- // delete the key from the redis server
- $this->redis->del($this->keys['session_id']);
- }
- parent::destroy();
- return $this;
- }
- // --------------------------------------------------------------------
- /**
- * Writes the redis entry
- *
- * @access private
- * @return boolean, true if it was an existing session, false if not
- */
- protected function _write_redis($session_id, $payload)
- {
- // write it to the redis server
- $this->redis->set($session_id, $payload);
- $this->redis->expire($session_id, $this->config['expiration_time']);
- }
- // --------------------------------------------------------------------
- /**
- * Reads the redis entry
- *
- * @access private
- * @return mixed, the payload if the file exists, or false if not
- */
- protected function _read_redis($session_id)
- {
- // fetch the session data from the Memcached server
- return $this->redis->get($session_id);
- }
- // --------------------------------------------------------------------
- /**
- * validate a driver config value
- *
- * @param array array with configuration values
- * @access public
- * @return array validated and consolidated config
- */
- public function _validate_config($config)
- {
- $validated = array();
- foreach ($config as $name => $item)
- {
- // filter out any driver config
- if (!is_array($item))
- {
- switch ($item)
- {
- case 'cookie_name':
- if ( empty($item) or ! is_string($item))
- {
- $item = 'fuelrid';
- }
- break;
- case 'database':
- // do we have a servers config
- if ( empty($item) or ! is_array($item))
- {
- $item = 'default';
- }
- break;
- default:
- break;
- }
- // global config, was validated in the driver
- $validated[$name] = $item;
- }
- }
- // validate all global settings as well
- return parent::_validate_config($validated);
- }
- }
|