Browse Source

Implementing Session timeout.

Making the timeout config the same as cookieTimeout, there is no reson
to have two different thinds that will just ocnfuse people.
Not forcing a timeout, but taking configurations from php.ini if exists.
Jose Lorenzo Rodriguez 12 years ago
parent
commit
a7f20375cf
2 changed files with 34 additions and 91 deletions
  1. 30 17
      src/Network/Session.php
  2. 4 74
      tests/TestCase/Network/SessionTest.php

+ 30 - 17
src/Network/Session.php

@@ -40,6 +40,10 @@ class Session {
 
 	protected $_started;
 
+	protected $_lifetime;
+
+	protected $_timeout;
+
 
 	public static function create($sessionConfig = []) {
 		if (isset($sessionConfig['defaults'])) {
@@ -53,14 +57,6 @@ class Session {
 			$sessionConfig['ini']['session.cookie_secure'] = 1;
 		}
 
-		if (isset($sessionConfig['timeout']) && !isset($sessionConfig['cookieTimeout'])) {
-			$sessionConfig['cookieTimeout'] = $sessionConfig['timeout'];
-		}
-
-		if (!isset($sessionConfig['ini']['session.cookie_lifetime'])) {
-			$sessionConfig['ini']['session.cookie_lifetime'] = $sessionConfig['cookieTimeout'] * 60;
-		}
-
 		if (!isset($sessionConfig['ini']['session.name'])) {
 			$sessionConfig['ini']['session.name'] = $sessionConfig['cookie'];
 		}
@@ -69,10 +65,6 @@ class Session {
 			$sessionConfig['ini']['session.save_handler'] = 'user';
 		}
 
-		if (!isset($sessionConfig['ini']['session.gc_maxlifetime'])) {
-			$sessionConfig['ini']['session.gc_maxlifetime'] = $sessionConfig['timeout'] * 60;
-		}
-
 		if (!isset($sessionConfig['ini']['session.cookie_httponly'])) {
 			$sessionConfig['ini']['session.cookie_httponly'] = 1;
 		}
@@ -91,7 +83,6 @@ class Session {
 			'php' => array(
 				'checkAgent' => false,
 				'cookie' => 'CAKEPHP',
-				'timeout' => 240,
 				'ini' => array(
 					'session.use_trans_sid' => 0,
 				)
@@ -99,7 +90,6 @@ class Session {
 			'cake' => array(
 				'checkAgent' => false,
 				'cookie' => 'CAKEPHP',
-				'timeout' => 240,
 				'ini' => array(
 					'session.use_trans_sid' => 0,
 					'url_rewriter.tags' => '',
@@ -112,7 +102,6 @@ class Session {
 			'cache' => array(
 				'checkAgent' => false,
 				'cookie' => 'CAKEPHP',
-				'timeout' => 240,
 				'ini' => array(
 					'session.use_trans_sid' => 0,
 					'url_rewriter.tags' => '',
@@ -127,7 +116,6 @@ class Session {
 			'database' => array(
 				'checkAgent' => false,
 				'cookie' => 'CAKEPHP',
-				'timeout' => 240,
 				'ini' => array(
 					'session.use_trans_sid' => 0,
 					'url_rewriter.tags' => '',
@@ -148,6 +136,11 @@ class Session {
 	}
 
 	public function __construct($config = []) {
+		if (isset($config['timeout'])) {
+			$config['ini']['session.cookie_lifetime'] = 60 * $config['timeout'];
+			$config['ini']['session.gc_maxlifetime'] = 60 * $config['timeout'];
+		}
+
 		if (!empty($config['ini']) && is_array($config['ini'])) {
 			$this->options($config['ini']);
 		}
@@ -163,6 +156,8 @@ class Session {
 			session_set_save_handler($this->engine($class, $config['handler']), false);
 		}
 
+		$this->_lifetime = ini_get('session.cookie_lifetime');
+		$this->_timeout = time() + $this->_lifetime;
 		session_register_shutdown();
 	}
 
@@ -235,8 +230,15 @@ class Session {
 		if (!session_start()) {
 			throw new \RuntimeException('Could not start the session');
 		}
+		
+		$this->_started = true;
+
+		if ($this->_timedOut()) {
+			$this->destroy();
+			return $this->start();
+		}
 
-		return $this->_started = true;
+		return $this->_started;
 	}
 
 /**
@@ -432,4 +434,15 @@ class Session {
 		session_regenerate_id(true);
 	}
 
+	protected function _timedOut() {
+		$time = $this->read('Config.time') ?: $this->_timeout;
+
+		if (!$this->_lifetime) {
+			return false;
+		}
+
+		$this->write('Config.time', $this->_timeout);
+		return $time > $this->_timeout;
+	}
+
 }

+ 4 - 74
tests/TestCase/Network/SessionTest.php

@@ -397,89 +397,19 @@ class SessionTest extends TestCase {
 	}
 
 /**
- * testSessionTimeout method
- *
- * @return void
- */
-	public function testSessionTimeout() {
-		Configure::write('debug', true);
-		Configure::write('Session.defaults', 'cake');
-		Configure::write('Session.autoRegenerate', false);
-
-		$timeoutSeconds = Configure::read('Session.timeout') * 60;
-
-		TestCakeSession::destroy();
-		TestCakeSession::write('Test', 'some value');
-
-		$this->assertWithinMargin(time() + $timeoutSeconds, Session::$sessionTime, 1);
-		$this->assertEquals(10, $_SESSION['Config']['countdown']);
-		$this->assertWithinMargin(Session::$sessionTime, $_SESSION['Config']['time'], 1);
-		$this->assertWithinMargin(time(), Session::$time, 1);
-		$this->assertWithinMargin(time() + $timeoutSeconds, $_SESSION['Config']['time'], 1);
-
-		Configure::write('Session.harden', true);
-		TestCakeSession::destroy();
-
-		TestCakeSession::write('Test', 'some value');
-		$this->assertWithinMargin(time() + $timeoutSeconds, Session::$sessionTime, 1);
-		$this->assertEquals(10, $_SESSION['Config']['countdown']);
-		$this->assertWithinMargin(Session::$sessionTime, $_SESSION['Config']['time'], 1);
-		$this->assertWithinMargin(time(), Session::$time, 1);
-		$this->assertWithinMargin(Session::$time + $timeoutSeconds, $_SESSION['Config']['time'], 1);
-	}
-
-/**
  * Test that cookieTimeout matches timeout when unspecified.
  *
  * @return void
  */
 	public function testCookieTimeoutFallback() {
-		$_SESSION = null;
-		Configure::write('Session', array(
+		$config = [
 			'defaults' => 'cake',
 			'timeout' => 400,
-		));
-		TestCakeSession::start();
-		$this->assertEquals(400, Configure::read('Session.cookieTimeout'));
-		$this->assertEquals(400, Configure::read('Session.timeout'));
+		];
+
+		$session = new Session($config);
 		$this->assertEquals(400 * 60, ini_get('session.cookie_lifetime'));
 		$this->assertEquals(400 * 60, ini_get('session.gc_maxlifetime'));
-
-		$_SESSION = null;
-		Configure::write('Session', array(
-			'defaults' => 'cake',
-			'timeout' => 400,
-			'cookieTimeout' => 600
-		));
-		TestCakeSession::start();
-		$this->assertEquals(600, Configure::read('Session.cookieTimeout'));
-		$this->assertEquals(400, Configure::read('Session.timeout'));
-	}
-
-/**
- * Proves that invalid sessions will be destroyed and re-created
- * if invalid
- *
- * @return void
- */
-	public function testInvalidSessionRenew() {
-		TestCakeSession::start();
-		$this->assertNotEmpty($_SESSION['Config']);
-		$data = $_SESSION;
-
-		session_write_close();
-		$_SESSION = null;
-
-		TestCakeSession::start();
-		$this->assertEquals($data, $_SESSION);
-		TestCakeSession::write('Foo', 'Bar');
-
-		session_write_close();
-		$_SESSION = null;
-
-		TestCakeSession::userAgent('bogus!');
-		TestCakeSession::start();
-		$this->assertNotEquals($data, $_SESSION);
 	}
 
 }