From 3911cca404d67821f8f5d467dc49b08b05b41610 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Wed, 11 Dec 2019 16:09:40 -0800 Subject: [PATCH 1/5] Additional Session Prefix In big cloud environments, one Redis/keyDB instance used for many Magento installations. This prefix is necessary to properly manage sessions --- src/Cm/RedisSession/Handler.php | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Cm/RedisSession/Handler.php b/src/Cm/RedisSession/Handler.php index 671f099..86c0605 100644 --- a/src/Cm/RedisSession/Handler.php +++ b/src/Cm/RedisSession/Handler.php @@ -69,6 +69,11 @@ class Handler implements \SessionHandlerInterface * Session prefix */ const SESSION_PREFIX = 'sess_'; + + /** + * Additional Session prefix + */ + const SESSION_PREFIX_ADDITIONAL = ''; /** * Bots get shorter session lifetimes @@ -253,6 +258,13 @@ class Handler implements \SessionHandlerInterface * @var boolean */ private $_readOnly; + + /** + * Additional Configurable Prefix for Session + * + * @var string + */ + private $_prefixAdditional; /** * @param ConfigInterface $config @@ -284,6 +296,7 @@ public function __construct(ConfigInterface $config, LoggerInterface $logger, $r $this->_failAfter = $this->config->getFailAfter() ?: self::DEFAULT_FAIL_AFTER; $this->_maxLifetime = $this->config->getMaxLifetime() ?: self::DEFAULT_MAX_LIFETIME; $this->_minLifetime = $this->config->getMinLifetime() ?: self::DEFAULT_MIN_LIFETIME; + $this->_prefixAdditional = $this->config->getPrefix() ?: self::SESSION_PREFIX_ADDITIONAL; $this->_useLocking = ! $this->config->getDisableLocking(); // Use sleep time multiplier so fail after time is in seconds @@ -411,7 +424,7 @@ protected function hasConnection() public function read($sessionId) { // Get lock on session. Increment the "lock" field and if the new value is 1, we have the lock. - $sessionId = self::SESSION_PREFIX.$sessionId; + $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; $tries = $waiting = $lock = 0; $lockPid = $oldLockPid = null; // Restart waiting for lock when current lock holder changes $detectZombies = false; @@ -616,6 +629,8 @@ public function read($sessionId) */ public function write($sessionId, $sessionData) { + $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; + if ($this->_sessionWritten || $this->_readOnly) { $this->_log(sprintf(($this->_sessionWritten ? "Repeated" : "Read-only") . " session write detected; skipping for ID %s", $sessionId)); return true; @@ -628,7 +643,7 @@ public function write($sessionId, $sessionData) if($this->_dbNum) $this->_redis->select($this->_dbNum); // Prevent conflicts with other connections? if ( ! $this->_useLocking - || ( ! ($pid = $this->_redis->hGet('sess_'.$sessionId, 'pid')) || $pid == $this->_getPid()) + || ( ! ($pid = $this->_redis->hGet($sessionId, 'pid')) || $pid == $this->_getPid()) ) { $this->_writeRawSession($sessionId, $sessionData, $this->getLifeTime()); $this->_log(sprintf("Data written to ID %s in %.5f seconds", $sessionId, (microtime(true) - $timeStart))); @@ -661,6 +676,8 @@ public function write($sessionId, $sessionData) */ public function destroy($sessionId) { + + = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; $this->_log(sprintf("Destroying ID %s", $sessionId)); $this->_redis->pipeline(); if($this->_dbNum) $this->_redis->select($this->_dbNum); @@ -828,7 +845,7 @@ protected function _decodeData($data) */ protected function _writeRawSession($id, $data, $lifetime) { - $sessionId = 'sess_' . $id; + $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; $this->_redis->pipeline() ->select($this->_dbNum) ->hMSet($sessionId, array( From c41275d80f77051f827fb29d1f2b656bd6091d9d Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Wed, 11 Dec 2019 16:24:08 -0800 Subject: [PATCH 2/5] Fix sessionId var Fix missing sessionId --- src/Cm/RedisSession/Handler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cm/RedisSession/Handler.php b/src/Cm/RedisSession/Handler.php index 86c0605..7b1d6ec 100644 --- a/src/Cm/RedisSession/Handler.php +++ b/src/Cm/RedisSession/Handler.php @@ -677,7 +677,7 @@ public function write($sessionId, $sessionData) public function destroy($sessionId) { - = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; + $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; $this->_log(sprintf("Destroying ID %s", $sessionId)); $this->_redis->pipeline(); if($this->_dbNum) $this->_redis->select($this->_dbNum); From edcd41bb476642b03fb7c5f681788b47fb369cd4 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Thu, 12 Dec 2019 10:10:52 -0800 Subject: [PATCH 3/5] Change the constant back --- src/Cm/RedisSession/Handler.php | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Cm/RedisSession/Handler.php b/src/Cm/RedisSession/Handler.php index 7b1d6ec..d84f38f 100644 --- a/src/Cm/RedisSession/Handler.php +++ b/src/Cm/RedisSession/Handler.php @@ -69,11 +69,6 @@ class Handler implements \SessionHandlerInterface * Session prefix */ const SESSION_PREFIX = 'sess_'; - - /** - * Additional Session prefix - */ - const SESSION_PREFIX_ADDITIONAL = ''; /** * Bots get shorter session lifetimes @@ -296,7 +291,7 @@ public function __construct(ConfigInterface $config, LoggerInterface $logger, $r $this->_failAfter = $this->config->getFailAfter() ?: self::DEFAULT_FAIL_AFTER; $this->_maxLifetime = $this->config->getMaxLifetime() ?: self::DEFAULT_MAX_LIFETIME; $this->_minLifetime = $this->config->getMinLifetime() ?: self::DEFAULT_MIN_LIFETIME; - $this->_prefixAdditional = $this->config->getPrefix() ?: self::SESSION_PREFIX_ADDITIONAL; + $this->_prefixAdditional = $this->config->getPrefix() ?: ''; $this->_useLocking = ! $this->config->getDisableLocking(); // Use sleep time multiplier so fail after time is in seconds @@ -424,7 +419,7 @@ protected function hasConnection() public function read($sessionId) { // Get lock on session. Increment the "lock" field and if the new value is 1, we have the lock. - $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; + $sessionId = 'sess_'.$this->_prefixAdditional.$sessionId; $tries = $waiting = $lock = 0; $lockPid = $oldLockPid = null; // Restart waiting for lock when current lock holder changes $detectZombies = false; @@ -629,7 +624,7 @@ public function read($sessionId) */ public function write($sessionId, $sessionData) { - $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; + $sessionId = 'sess_'.$this->_prefixAdditional.$sessionId; if ($this->_sessionWritten || $this->_readOnly) { $this->_log(sprintf(($this->_sessionWritten ? "Repeated" : "Read-only") . " session write detected; skipping for ID %s", $sessionId)); @@ -677,11 +672,11 @@ public function write($sessionId, $sessionData) public function destroy($sessionId) { - $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; + $sessionId = 'sess_'.$this->_prefixAdditional.$sessionId; $this->_log(sprintf("Destroying ID %s", $sessionId)); $this->_redis->pipeline(); if($this->_dbNum) $this->_redis->select($this->_dbNum); - $this->_redis->del(self::SESSION_PREFIX.$sessionId); + $this->_redis->del('sess_'.$sessionId); $this->_redis->exec(); return true; } @@ -845,7 +840,7 @@ protected function _decodeData($data) */ protected function _writeRawSession($id, $data, $lifetime) { - $sessionId = self::SESSION_PREFIX.$this->_prefixAdditional.$sessionId; + $sessionId = 'sess_'.$this->_prefixAdditional.$sessionId; $this->_redis->pipeline() ->select($this->_dbNum) ->hMSet($sessionId, array( From 0fbe65ca0fbb3274b0de402524ca1f321ff79ba8 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Thu, 12 Dec 2019 12:28:07 -0800 Subject: [PATCH 4/5] Fix Session Id prefix duplicates --- src/Cm/RedisSession/Handler.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Cm/RedisSession/Handler.php b/src/Cm/RedisSession/Handler.php index d84f38f..5be8c80 100644 --- a/src/Cm/RedisSession/Handler.php +++ b/src/Cm/RedisSession/Handler.php @@ -676,7 +676,7 @@ public function destroy($sessionId) $this->_log(sprintf("Destroying ID %s", $sessionId)); $this->_redis->pipeline(); if($this->_dbNum) $this->_redis->select($this->_dbNum); - $this->_redis->del('sess_'.$sessionId); + $this->_redis->del($sessionId); $this->_redis->exec(); return true; } @@ -840,15 +840,14 @@ protected function _decodeData($data) */ protected function _writeRawSession($id, $data, $lifetime) { - $sessionId = 'sess_'.$this->_prefixAdditional.$sessionId; $this->_redis->pipeline() ->select($this->_dbNum) - ->hMSet($sessionId, array( + ->hMSet($id, array( 'data' => $this->_encodeData($data), 'lock' => 0, // 0 so that next lock attempt will get 1 )) - ->hIncrBy($sessionId, 'writes', 1) - ->expire($sessionId, min((int)$lifetime, (int)$this->_maxLifetime)) + ->hIncrBy($id, 'writes', 1) + ->expire($id, min((int)$lifetime, (int)$this->_maxLifetime)) ->exec(); } From c794491a66f3c4c2d07ef894ae1d52d59f9f3dc6 Mon Sep 17 00:00:00 2001 From: Egor Shitikov Date: Thu, 12 Dec 2019 13:43:18 -0800 Subject: [PATCH 5/5] Add getPrefix to the Interface Get configurable prefix for session ID method --- src/Cm/RedisSession/Handler/ConfigInterface.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Cm/RedisSession/Handler/ConfigInterface.php b/src/Cm/RedisSession/Handler/ConfigInterface.php index a315c20..db9a760 100644 --- a/src/Cm/RedisSession/Handler/ConfigInterface.php +++ b/src/Cm/RedisSession/Handler/ConfigInterface.php @@ -192,4 +192,14 @@ public function getSentinelVerifyMaster(); * @return string */ public function getSentinelConnectRetries(); + + + /** + * Get configurable prefix for session ID + * + * @return string + */ + public function getPrefix(); + + }