PageRenderTime 32ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/session/SessionManager.inc.php

https://github.com/mbehiels/pkp-lib
PHP | 256 lines | 130 code | 35 blank | 91 comment | 22 complexity | ad94b3ab02da6d80e3894133e8e2fa9c MD5 | raw file
  1. <?php
  2. /**
  3. * @file classes/session/SessionManager.inc.php
  4. *
  5. * Copyright (c) 2000-2011 John Willinsky
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @class SessionManager
  9. * @ingroup session
  10. *
  11. * @brief Implements PHP methods for a custom session storage handler (see http://php.net/session).
  12. */
  13. class SessionManager {
  14. /** @var object The DAO for accessing Session objects */
  15. var $sessionDao;
  16. /** @var object The Session associated with the current request */
  17. var $userSession;
  18. /**
  19. * Constructor.
  20. * Initialize session configuration and set PHP session handlers.
  21. * Attempts to rejoin a user's session if it exists, or create a new session otherwise.
  22. * @param $sessionDao SessionDAO
  23. * @param $request PKPRequest
  24. */
  25. function SessionManager(&$sessionDao, &$request) {
  26. $this->sessionDao =& $sessionDao;
  27. // Configure PHP session parameters
  28. ini_set('session.use_trans_sid', 0);
  29. ini_set('session.save_handler', 'user');
  30. ini_set('session.serialize_handler', 'php');
  31. ini_set('session.use_cookies', 1);
  32. ini_set('session.name', Config::getVar('general', 'session_cookie_name')); // Cookie name
  33. ini_set('session.cookie_lifetime', 0);
  34. ini_set('session.cookie_path', $request->getBasePath() . '/');
  35. ini_set('session.gc_probability', 1);
  36. ini_set('session.gc_maxlifetime', 60 * 60);
  37. ini_set('session.auto_start', 1);
  38. ini_set('session.cache_limiter', 'none');
  39. session_set_save_handler(
  40. array(&$this, 'open'),
  41. array(&$this, 'close'),
  42. array(&$this, 'read'),
  43. array(&$this, 'write'),
  44. array(&$this, 'destroy'),
  45. array(&$this, 'gc')
  46. );
  47. // Initialize the session. This calls SessionManager::read() and
  48. // sets $this->userSession if a session is present.
  49. session_start();
  50. $sessionId = session_id();
  51. $ip = $request->getRemoteAddr();
  52. $userAgent = $request->getUserAgent();
  53. $now = time();
  54. if (!isset($this->userSession) || (Config::getVar('security', 'session_check_ip') && $this->userSession->getIpAddress() != $ip) || $this->userSession->getUserAgent() != substr($userAgent, 0, 255)) {
  55. if (isset($this->userSession)) {
  56. // Destroy old session
  57. session_destroy();
  58. }
  59. // Create new session
  60. $this->userSession = new Session();
  61. $this->userSession->setId($sessionId);
  62. $this->userSession->setIpAddress($ip);
  63. $this->userSession->setUserAgent($userAgent);
  64. $this->userSession->setSecondsCreated($now);
  65. $this->userSession->setSecondsLastUsed($now);
  66. $this->userSession->setSessionData('');
  67. $this->sessionDao->insertSession($this->userSession);
  68. } else {
  69. if ($this->userSession->getRemember()) {
  70. // Update session timestamp for remembered sessions so it doesn't expire in the middle of a browser session
  71. if (Config::getVar('general', 'session_lifetime') > 0) {
  72. $this->updateSessionLifetime(time() + Config::getVar('general', 'session_lifetime') * 86400);
  73. } else {
  74. $this->userSession->setRemember(0);
  75. $this->updateSessionLifetime(0);
  76. }
  77. }
  78. // Update existing session's timestamp; will be saved when write is called
  79. $this->userSession->setSecondsLastUsed($now);
  80. }
  81. }
  82. /**
  83. * Return an instance of the session manager.
  84. * @return SessionManager
  85. */
  86. function &getManager() {
  87. $instance =& Registry::get('sessionManager', true, null);
  88. if (is_null($instance)) {
  89. $application =& Registry::get('application');
  90. assert(!is_null($application));
  91. $request =& $application->getRequest();
  92. assert(!is_null($request));
  93. // Implicitly set session manager by ref in the registry
  94. $instance = new SessionManager(DAORegistry::getDAO('SessionDAO'), $request);
  95. }
  96. return $instance;
  97. }
  98. /**
  99. * Get the session associated with the current request.
  100. * @return Session
  101. */
  102. function &getUserSession() {
  103. return $this->userSession;
  104. }
  105. /**
  106. * Open a session.
  107. * Does nothing; only here to satisfy PHP session handler requirements.
  108. * @return boolean
  109. */
  110. function open() {
  111. return true;
  112. }
  113. /**
  114. * Close a session.
  115. * Does nothing; only here to satisfy PHP session handler requirements.
  116. * @return boolean
  117. */
  118. function close() {
  119. return true;
  120. }
  121. /**
  122. * Read session data from database.
  123. * @param $sessionId string
  124. * @return boolean
  125. */
  126. function read($sessionId) {
  127. if (!isset($this->userSession)) {
  128. $this->userSession =& $this->sessionDao->getSession($sessionId);
  129. if (isset($this->userSession)) {
  130. $data = $this->userSession->getSessionData();
  131. }
  132. }
  133. return isset($data) ? $data : '';
  134. }
  135. /**
  136. * Save session data to database.
  137. * @param $sessionId string
  138. * @param $data array
  139. * @return boolean
  140. */
  141. function write($sessionId, $data) {
  142. if (isset($this->userSession)) {
  143. $this->userSession->setSessionData($data);
  144. return $this->sessionDao->updateObject($this->userSession);
  145. } else {
  146. return true;
  147. }
  148. }
  149. /**
  150. * Destroy (delete) a session.
  151. * @param $sessionId string
  152. * @return boolean
  153. */
  154. function destroy($sessionId) {
  155. return $this->sessionDao->deleteSessionById($sessionId);
  156. }
  157. /**
  158. * Garbage collect unused session data.
  159. * TODO: Use $maxlifetime instead of assuming 24 hours?
  160. * @param $maxlifetime int the number of seconds after which data will be seen as "garbage" and cleaned up
  161. * @return boolean
  162. */
  163. function gc($maxlifetime) {
  164. return $this->sessionDao->deleteSessionByLastUsed(time() - 86400, Config::getVar('general', 'session_lifetime') <= 0 ? 0 : time() - Config::getVar('general', 'session_lifetime') * 86400);
  165. }
  166. /**
  167. * Resubmit the session cookie.
  168. * @param $sessionId string new session ID (or false to keep current ID)
  169. * @param $expireTime int new expiration time in seconds (0 = current session)
  170. * @return boolean
  171. */
  172. function updateSessionCookie($sessionId = false, $expireTime = 0) {
  173. return setcookie(session_name(), ($sessionId === false) ? session_id() : $sessionId, $expireTime, ini_get('session.cookie_path'));
  174. }
  175. /**
  176. * Regenerate the session ID for the current user session.
  177. * This is useful to guard against the "session fixation" form of hijacking
  178. * by changing the user's session ID after they have logged in (in case the
  179. * original session ID had been pre-populated).
  180. * @return boolean
  181. */
  182. function regenerateSessionId() {
  183. $success = false;
  184. $currentSessionId = session_id();
  185. if (function_exists('session_regenerate_id')) {
  186. // session_regenerate_id is only available on PHP >= 4.3.2
  187. if (session_regenerate_id() && isset($this->userSession)) {
  188. // Delete old session and insert new session
  189. $this->sessionDao->deleteSessionById($currentSessionId);
  190. $this->userSession->setId(session_id());
  191. $this->sessionDao->insertSession($this->userSession);
  192. $this->updateSessionCookie(); // TODO: this might not be needed on >= 4.3.3
  193. $success = true;
  194. }
  195. } else {
  196. // Regenerate session ID (for PHP < 4.3.2)
  197. do {
  198. // Generate new session ID -- should be random enough to typically execute only once
  199. $newSessionId = md5(mt_rand());
  200. } while ($this->sessionDao->sessionExistsById($newSessionId));
  201. if (isset($this->userSession)) {
  202. // Delete old session and insert new session
  203. $this->sessionDao->deleteSessionById($currentSessionId);
  204. $this->userSession->setId($newSessionId);
  205. $this->sessionDao->insertSession($this->userSession);
  206. $this->updateSessionCookie($newSessionId);
  207. $success = true;
  208. }
  209. }
  210. return $success;
  211. }
  212. /**
  213. * Change the lifetime of the current session cookie.
  214. * @param $expireTime int new expiration time in seconds (0 = current session)
  215. * @return boolean
  216. */
  217. function updateSessionLifetime($expireTime = 0) {
  218. return $this->updateSessionCookie(false, $expireTime);
  219. }
  220. }
  221. ?>