PageRenderTime 39ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/session/Session_cache.php

https://github.com/danmontgomery/codeigniter-session-driver
PHP | 302 lines | 173 code | 54 blank | 75 comment | 23 complexity | 75fb32e769f9d97de339c1ec1c6b722a MD5 | raw file
  1. <?php
  2. class Session_cache extends CI_Driver {
  3. protected $CI;
  4. protected $sess_id;
  5. protected $sess_cache_driver;
  6. protected $sess_encrypt_cookie;
  7. protected $sess_cookie_name;
  8. protected $cookie_prefix;
  9. protected $cookie_path;
  10. protected $cookie_domain;
  11. protected $cookie_secure;
  12. public function __construct()
  13. {
  14. $this->CI = get_instance();
  15. foreach (array('sess_cache_driver','sess_encrypt_cookie','sess_cookie_name','cookie_prefix','cookie_path','cookie_domain','cookie_secure') as $key)
  16. {
  17. $this->$key = $this->CI->config->item($key);
  18. }
  19. // Load cache library, assign it to the object
  20. $this->CI->load->driver('cache', array('adapter' => $this->sess_cache_driver));
  21. }
  22. // --------------------------------------------------------------------
  23. /**
  24. * Fetch the current session data if it exists
  25. *
  26. * @access public
  27. * @return bool
  28. */
  29. public function sess_read()
  30. {
  31. // Fetch the cookie
  32. $session = $this->CI->input->cookie($this->sess_cookie_name);
  33. // No cookie? Goodbye cruel world!...
  34. if ($session === FALSE)
  35. {
  36. log_message('debug', 'A session cookie was not found.');
  37. return FALSE;
  38. }
  39. // Decrypt the cookie data
  40. if ($this->sess_encrypt_cookie == TRUE)
  41. {
  42. $session = $this->CI->encrypt->decode($session);
  43. }
  44. else
  45. {
  46. // encryption was not used, so we need to check the md5 hash
  47. $hash = substr($session, strlen($session)-32); // get last 32 chars
  48. $session = substr($session, 0, strlen($session)-32);
  49. // Does the md5 hash match? This is to prevent manipulation of session data in userspace
  50. if ($hash !== md5($session.$this->parent->encryption_key))
  51. {
  52. log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
  53. $this->sess_destroy();
  54. return FALSE;
  55. }
  56. }
  57. // Unserialize the session array
  58. $session = $this->parent->_unserialize($session);
  59. if( ! is_array($session) OR ! isset($session['session_id']))
  60. {
  61. $this->sess_destroy();
  62. return FALSE;
  63. }
  64. $this->sess_id = $session['session_id'];
  65. // Is there a corresponding session in the cache?
  66. $cache = $this->CI->cache->get($this->sess_id);
  67. if($cache === FALSE)
  68. {
  69. log_message('debug', 'Session not found in cache.');
  70. return FALSE;
  71. }
  72. $cache = $this->parent->_unserialize($cache);
  73. // Is the session data we unserialized an array with the correct format?
  74. if ( ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']) OR ! is_array($cache) OR ! isset($cache['session_id']) OR ! isset($cache['ip_address']) OR ! isset($cache['user_agent']) OR ! isset($cache['last_activity']))
  75. {
  76. $this->sess_destroy();
  77. return FALSE;
  78. }
  79. // Is the session current?
  80. if (($session['last_activity'] + $this->parent->sess_expiration) < $this->parent->now)
  81. {
  82. $this->sess_destroy();
  83. return FALSE;
  84. }
  85. // Does the IP Match?
  86. if ($this->parent->sess_match_ip == TRUE AND ($session['ip_address'] != $this->CI->input->ip_address() OR $cache['ip_address'] != $this->CI->input->ip_address()))
  87. {
  88. $this->sess_destroy();
  89. return FALSE;
  90. }
  91. // Does the User Agent Match?
  92. if ($this->parent->sess_match_useragent == TRUE AND (trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 120)) OR trim($cache['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 120))))
  93. {
  94. $this->sess_destroy();
  95. return FALSE;
  96. }
  97. // Session is valid!
  98. $this->parent->userdata = $cache;
  99. unset($session, $cache);
  100. return TRUE;
  101. }
  102. // --------------------------------------------------------------------
  103. /**
  104. * Write the session data
  105. *
  106. * @access public
  107. * @return void
  108. */
  109. public function sess_write()
  110. {
  111. if( ! $this->parent->check_write())
  112. {
  113. $this->CI->cache->save($this->sess_id, $this->parent->_serialize($this->parent->userdata), $this->parent->sess_expiration);
  114. $this->parent->track_write();
  115. $this->_set_cookie();
  116. }
  117. }
  118. // --------------------------------------------------------------------
  119. /**
  120. * Create a new session
  121. *
  122. * @access public
  123. * @return void
  124. */
  125. public function sess_create()
  126. {
  127. $sessid = '';
  128. while (strlen($sessid) < 32)
  129. {
  130. $sessid .= mt_rand(0, mt_getrandmax());
  131. }
  132. $this->sess_id = md5(uniqid($sessid.$this->CI->input->ip_address(), TRUE));
  133. $this->parent->userdata = array(
  134. 'session_id' => $this->sess_id,
  135. 'ip_address' => $this->CI->input->ip_address(),
  136. 'user_agent' => substr($this->CI->input->user_agent(), 0, 120),
  137. 'last_activity' => $this->parent->now
  138. );
  139. $custom_userdata = array('user_data' => '');
  140. // Save session to cache
  141. $this->CI->cache->save($this->sess_id, $this->parent->userdata+$custom_userdata);
  142. // Write the cookie
  143. $this->_set_cookie();
  144. }
  145. // --------------------------------------------------------------------
  146. /**
  147. * Update an existing session
  148. *
  149. * @access public
  150. * @return void
  151. */
  152. public function sess_update()
  153. {
  154. // We only update the session every five minutes by default
  155. if (($this->parent->userdata['last_activity'] + $this->parent->sess_time_to_update) >= $this->parent->now)
  156. {
  157. return;
  158. }
  159. // Save the old session id so we know which record to
  160. // update in the database if we need it
  161. $old_sessid = $this->sess_id;
  162. $new_sessid = '';
  163. while (strlen($new_sessid) < 32)
  164. {
  165. $new_sessid .= mt_rand(0, mt_getrandmax());
  166. }
  167. // To make the session ID even more secure we'll combine it with the user's IP, then hash
  168. $this->sess_id = md5(uniqid($new_sessid.$this->CI->input->ip_address(), TRUE));
  169. // Update the session data in the session data array
  170. $this->parent->userdata['session_id'] = $this->sess_id;
  171. $this->parent->userdata['last_activity'] = $this->now;
  172. // Save new cache, delete old cache
  173. $this->CI->cache->save($this->sess_id, $this->parent->_serialize($this->parent->userdata), $this->parent->sess_expiration);
  174. $this->CI->cache->delete($old_sessid);
  175. // Write the cookie
  176. $this->_set_cookie();
  177. }
  178. // --------------------------------------------------------------------
  179. /**
  180. * Destroy the current session
  181. *
  182. * @access public
  183. * @return void
  184. */
  185. public function sess_destroy()
  186. {
  187. if( ! empty($this->sess_id))
  188. {
  189. $this->CI->cache->delete($this->sess_id);
  190. }
  191. $this->parent->userdata = array();
  192. $this->sess_id = '';
  193. // Kill the cookie
  194. setcookie(
  195. $this->sess_cookie_name,
  196. addslashes(serialize(array())),
  197. ($this->parent->now - 31500000),
  198. $this->cookie_path,
  199. $this->cookie_domain,
  200. 0
  201. );
  202. }
  203. // --------------------------------------------------------------------
  204. /**
  205. * Does nothing for cache sessions
  206. *
  207. * @access private
  208. * @return void
  209. */
  210. public function _sess_gc(){}
  211. // --------------------------------------------------------------------
  212. /**
  213. * Write the session cookie
  214. *
  215. * @access private
  216. * @return void
  217. */
  218. protected function _set_cookie()
  219. {
  220. $cookie_data = array(
  221. 'session_id' => $this->parent->userdata['session_id'],
  222. 'ip_address' => $this->parent->userdata['ip_address'],
  223. 'user_agent' => $this->parent->userdata['user_agent'],
  224. 'last_activity' => $this->parent->userdata['last_activity']
  225. );
  226. // Serialize the userdata for the cookie
  227. $cookie_data = $this->parent->_serialize($cookie_data);
  228. if ($this->sess_encrypt_cookie == TRUE)
  229. {
  230. $cookie_data = $this->CI->encrypt->encode($cookie_data);
  231. }
  232. else
  233. {
  234. // if encryption is not used, we provide an md5 hash to prevent userside tampering
  235. $cookie_data = $cookie_data.md5($cookie_data.$this->parent->encryption_key);
  236. }
  237. $expire = $this->parent->sess_expiration + time();
  238. // Set the cookie
  239. setcookie(
  240. $this->sess_cookie_name,
  241. $cookie_data,
  242. $expire,
  243. $this->cookie_path,
  244. $this->cookie_domain,
  245. $this->cookie_secure
  246. );
  247. }
  248. }