From 4156cc5c0418e9937f13edb4a510729b10f5c7b1 Mon Sep 17 00:00:00 2001 From: "Bruno O. Notario" Date: Wed, 21 Feb 2024 23:42:00 -0300 Subject: [PATCH] Fix lifetime session database handler --- system/encryption/autoload.php | 37 +++++++++++++++++++++- system/session/Api/HandlerInterface.php | 7 +++++ system/session/Handlers/Database.php | 41 ++++++++++++++++++++++--- system/session/Redis/Config.php | 4 +-- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/system/encryption/autoload.php b/system/encryption/autoload.php index 61f07ea..0bacbc6 100644 --- a/system/encryption/autoload.php +++ b/system/encryption/autoload.php @@ -19,6 +19,8 @@ class Encryption { private $method; private $cipher; + private $hash_algo = 'sha256'; + /** * @param string $key * @param string $opensslCipher @@ -44,12 +46,45 @@ class Encryption { return $this->key; } + /** + * @param string $hashAlgorithm + * @return $this + * @throws \Phacil\Framework\Exception\InvalidArgumentException + */ + public function setHashAlgorithm($hashAlgorithm) { + if (!in_array($hashAlgorithm, hash_algos())) { + throw new \Phacil\Framework\Exception\InvalidArgumentException("The hash algorithm '${hashAlgorithm}' is not available."); + } + $this->hash_algo = $hashAlgorithm; + return $this; + } + + /** + * @param string $hashAlgorithm + * @return $this + * @throws \Phacil\Framework\Exception\InvalidArgumentException + */ + public function setHashAlgo($hashAlgorithm){ + return $this->setHashAlgorithm($hashAlgorithm); + } + + /** @return string */ + public function getHashAlgorithm() { + return $this->hash_algo; + } + + /** @return string */ + public function getHashAlgo(){ + return $this->getHashAlgorithm(); + } + /** * @param string $value * @return string|false */ public function hash($value) { - return hash('sha256', $value, true); + //return hash_hmac() + return hash($this->getHashAlgorithm(), $value); } /** diff --git a/system/session/Api/HandlerInterface.php b/system/session/Api/HandlerInterface.php index fa03334..6158960 100644 --- a/system/session/Api/HandlerInterface.php +++ b/system/session/Api/HandlerInterface.php @@ -15,6 +15,13 @@ namespace Phacil\Framework\Session\Api; */ interface HandlerInterface extends \SessionHandlerInterface { + /** + * Session max lifetime + */ + const DEFAULT_SESSION_LIFETIME = 1800; + + const DEFAULT_SESSION_FIRST_LIFETIME = 600; + /** * Get the number of failed lock attempts * diff --git a/system/session/Handlers/Database.php b/system/session/Handlers/Database.php index 3e2adf3..2d6d5a1 100644 --- a/system/session/Handlers/Database.php +++ b/system/session/Handlers/Database.php @@ -10,6 +10,7 @@ use Phacil\Framework\Api\Database as FrameworkDatabase; use Phacil\Framework\Encryption; +use Phacil\Framework\Config as FrameworkConfig; /** * Data base session save handler @@ -44,24 +45,37 @@ class Database implements \Phacil\Framework\Session\Api\HandlerInterface */ private $encryptor; + private $config; + /** + * @param \Phacil\Framework\Api\Database $resource + * @param \Phacil\Framework\Encryption $encryptor + * @return void + */ public function __construct( FrameworkDatabase $resource, - Encryption $encryptor + Encryption $encryptor, + FrameworkConfig $config ) { $this->_sessionTable = self::TABLE_NAME; $this->connection = $resource->query(); $this->checkConnection(); $this->encryptor = $encryptor; + $this->config = $config; } public function getFailedLockAttempts() { } public function setName($name) { } + /** + * @param string $hash + * @return string|false + */ private function hashed($hash) { - //return $this->encryptor->hash($hash); - return $hash; + //$this->encryptor->setHashAlgo('sha256'); + return $this->encryptor->hash($hash) ?: $hash; + //return $hash; } /** @@ -84,6 +98,16 @@ class Database implements \Phacil\Framework\Session\Api\HandlerInterface } } + /** @return int */ + protected function getLifetime() { + return (int)$this->config->get('session_expire') ?: self::DEFAULT_SESSION_LIFETIME; + } + + /** @return int */ + protected function getFirstLifetime() { + return (int)$this->config->get('session_first_lifetime') ?: self::DEFAULT_SESSION_FIRST_LIFETIME; + } + /** * Open session * @@ -130,6 +154,11 @@ class Database implements \Phacil\Framework\Session\Api\HandlerInterface return null; } + if($data->getRow()->getValue(self::COLUMN_EXPIRES) < time()){ + $this->destroy($sessionId); + return null; + } + $data = $data->getRow()->getValue(self::COLUMN_DATA); // check if session data is a base64 encoded string @@ -157,7 +186,7 @@ class Database implements \Phacil\Framework\Session\Api\HandlerInterface // encode session serialized data to prevent insertion of incorrect symbols $sessionData = base64_encode($sessionData); - $bind = [self::COLUMN_EXPIRES => time(), self::COLUMN_DATA => $sessionData]; + $bind = [self::COLUMN_EXPIRES => time() + $this->getLifetime(), self::COLUMN_DATA => $sessionData]; if ($exists->getNumRows() > 0) { $update = $this->connection->update($this->_sessionTable, $bind); @@ -165,6 +194,7 @@ class Database implements \Phacil\Framework\Session\Api\HandlerInterface $update->load(); } else { $bind[self::COLUMN_ID] = $hashedSessionId; + $bind[self::COLUMN_EXPIRES] = time() + $this->getFirstLifetime(); $this->connection->insert($this->_sessionTable, $bind)->load(); } return true; @@ -195,7 +225,8 @@ class Database implements \Phacil\Framework\Session\Api\HandlerInterface public function gc($maxLifeTime) { $del = $this->connection->delete($this->_sessionTable); - $del->where()->lessThan(self::COLUMN_EXPIRES, time() - $maxLifeTime); + //$del->where()->lessThan(self::COLUMN_EXPIRES, time() - $maxLifeTime); + $del->where()->lessThan(self::COLUMN_EXPIRES, time()); return $del->load(); } } diff --git a/system/session/Redis/Config.php b/system/session/Redis/Config.php index ad0ce25..990b7a1 100644 --- a/system/session/Redis/Config.php +++ b/system/session/Redis/Config.php @@ -203,7 +203,7 @@ class Config implements ConfigInterface { */ public function getFirstLifetime() { - return (int)$this->config->get('session_redis_first_lifetime') ?: (self::PARAM_FIRST_LIFETIME); + return (int)$this->config->get('session_first_lifetime') ?: (\Phacil\Framework\Session\Api\HandlerInterface::DEFAULT_SESSION_FIRST_LIFETIME); } /** @@ -219,7 +219,7 @@ class Config implements ConfigInterface { */ public function getLifetime() { - return (int)$this->config->get('session_redis_expire') ?: self::PARAM_SESSION_LIFETIME; + return (int)$this->config->get('session_expire') ?: \Phacil\Framework\Session\Api\HandlerInterface::DEFAULT_SESSION_LIFETIME; } /**