Просмотр исходного кода

#4646 Session optimization: set session cookie lifetime correctly, add TTL, use it for remember me, delete expired cookies by TTL and by session idle time(1d), don't send set-cookie each time

Alex Trofimov 1 год назад
Родитель
Сommit
61c710a894
3 измененных файлов с 49 добавлено и 16 удалено
  1. 38 6
      inc/classes/BxDolSession.php
  2. 8 9
      inc/classes/BxDolSessionQuery.php
  3. 3 1
      install/sql/system.sql

+ 38 - 6
inc/classes/BxDolSession.php

@@ -7,8 +7,8 @@
  * @{
  */
 
-if (!defined('BX_DOL_SESSION_LIFETIME'))
-    define('BX_DOL_SESSION_LIFETIME', 7*24*60*60);
+if (!defined('BX_DOL_SESSION_IDLE_TIMEOUT'))
+    define('BX_DOL_SESSION_IDLE_TIMEOUT', 1*24*60*60);
 if (!defined('BX_DOL_SESSION_SKIP_UPDATE'))
     define('BX_DOL_SESSION_SKIP_UPDATE', 30);
 define('BX_DOL_SESSION_COOKIE', 'memberSession');
@@ -19,6 +19,7 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
     protected $sId;
     protected $iUserId;
     protected $aData;
+    protected $iTTL;
 
     protected $bAutoLogout;	//--- Auto logout with broken session
 
@@ -33,8 +34,9 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
         $this->sId = '';
         $this->iUserId = 0;
         $this->aData = array();
+        $this->iTTL = 0;
 
-        $this->bAutoLogout = false; // when changing to 'true', it's better to increase BX_DOL_SESSION_LIFETIME to 1 month or so
+        $this->bAutoLogout = false; // when changing to 'true', it maybe you will need to increase BX_DOL_SESSION_IDLE_TIMEOUT
         if (defined('BX_SESSION_AUTO_LOGOUT'))
             $this->bAutoLogout = BX_SESSION_AUTO_LOGOUT;
     }
@@ -103,12 +105,19 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
 		if (!$this->sId)
             $this->sId = genRndPwd(32, true);
 
-        $iTime = time() + BX_DOL_SESSION_LIFETIME;
-        if (getParam('sys_session_auth') && $this->isValue('remember_me') && !$this->getValue('remember_me'))
+        if (!isset($_COOKIE[BX_DOL_SESSION_COOKIE]) || $_COOKIE[BX_DOL_SESSION_COOKIE] != $this->sId || $this->isValue('remember_me')) {
             $iTime = 0;
-        bx_setcookie(BX_DOL_SESSION_COOKIE, $this->sId, $iTime, 'auto', '', 'auto', true);
+            if (getParam('sys_session_auth') && $this->isValue('remember_me') && $this->getValue('remember_me'))
+                $iTime = time() + getParam('sys_session_lifetime_in_min') * 60;
+
+            bx_setcookie(BX_DOL_SESSION_COOKIE, $this->sId, $iTime, 'auto', '', 'auto', true);
+            $this->iTTL = $iTime;
+            unset($this->aData['remember_me']);
+        }
 
         $this->save();
+
+
         return true;
     }
 
@@ -129,6 +138,7 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
 
         $this->sId = '';
         $this->iUserId = 0;
+        $this->iTTL = 0;
         $this->aData = array();
     }
 
@@ -143,6 +153,7 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
 
 		$this->sId = $mixedSession['id'];
 		$this->iUserId = (int)$mixedSession['user_id'];
+        $this->iTTL = (int)$mixedSession['ttl'];
 		$this->aData = unserialize($mixedSession['data']);
 
 		$this->oDb->update($this->sId);		//--- update session's time
@@ -177,6 +188,26 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
         return $this->iUserId;
     }
 
+    function setTTL($iTTL)
+    {
+        if(empty($this->sId))
+            $this->start();
+
+        if(empty($this->sId))
+            return;
+
+        $this->iTTL = $iTTL;
+        $this->save();
+    }
+    
+    function getTTL()
+    {
+        if(empty($this->sId))
+            $this->start();
+
+        return $this->iTTL;
+    }
+
     function setValue($sKey, $mixedValue)
     {
         if(empty($this->sId))
@@ -233,6 +264,7 @@ class BxDolSession extends BxDolFactory implements iBxDolSingleton
 
         $this->oDb->save($this->sId, array(
             'user_id' => $this->iUserId,
+            'ttl' => $this->iTTL,
             'data' => serialize($this->aData)
         ));
     }

+ 8 - 9
inc/classes/BxDolSessionQuery.php

@@ -26,7 +26,7 @@ class BxDolSessionQuery extends BxDolDb
     }
     function exists($sId)
     {
-        $aSession = $this->getRow("SELECT `id`, `user_id`, `data` FROM `" . $this->sTable . "` WHERE `id`=:id LIMIT 1", [
+        $aSession = $this->getRow("SELECT `id`, `user_id`, `ttl`, `data` FROM `" . $this->sTable . "` WHERE `id`=:id LIMIT 1", [
             'id' => (string)$sId
         ]);
 
@@ -40,7 +40,7 @@ class BxDolSessionQuery extends BxDolDb
         $aBind = $aSet;
         unset($aBind['date']);
 
-        if ($this->getOne("SELECT `date` FROM `" . $this->sTable . "` WHERE `id` = :id AND `data` = :data AND `user_id` = :user_id AND `date` > UNIX_TIMESTAMP() - " . BX_DOL_SESSION_SKIP_UPDATE, $aBind))
+        if ($this->getOne("SELECT `date` FROM `" . $this->sTable . "` WHERE `id` = :id AND `data` = :data AND `user_id` = :user_id AND `ttl` = :ttl AND `date` > UNIX_TIMESTAMP() - " . BX_DOL_SESSION_SKIP_UPDATE, $aBind))
             return true;
 
         $this->updateLastActivity($sId);
@@ -69,17 +69,16 @@ class BxDolSessionQuery extends BxDolDb
     }
     function deleteExpired()
     {
-        $iTime = time() - BX_DOL_SESSION_LIFETIME;
-        $sSql = $this->prepare("SELECT `user_id`, `date` FROM `" . $this->sTable . "` WHERE `date` < ? AND `user_id` != 0 ORDER BY `date` DESC LIMIT 50000", $iTime);
-        $aRows = $this->getAll($sSql);
+        $iTime = time() - BX_DOL_SESSION_IDLE_TIMEOUT;
+        $aRows = $this->getAll("SELECT `user_id`, `date` FROM `" . $this->sTable . "` WHERE ((`date` < :time AND `ttl` = 0) OR (`ttl` != 0 AND `ttl` < :now)) AND `user_id` != 0 ORDER BY `date` DESC LIMIT 50000", ['time' => $iTime, 'now' => time()]);
 
         foreach ($aRows as $aRow) {
             $this->updateLastActivityAccount($aRow['user_id'], $aRow['date']);
         }
-
-        $sSql = $this->prepare("DELETE FROM `" . $this->sTable . "` WHERE `date` < ?", $iTime);
-        $iRet = (int)$this->query($sSql);
-        if ($iRet)
+        
+        $iRet = (int)$this->query("DELETE FROM `" . $this->sTable . "` WHERE `date` < :time AND `ttl` = 0", ['time' => $iTime]);
+        $iRet += (int)$this->query("DELETE FROM `" . $this->sTable . "` WHERE `ttl` != 0 AND `ttl` < :now", ['now' => time()]);
+        if ($iRet > 10)
             $this->query("OPTIMIZE TABLE `" . $this->sTable . "`");
         return $iRet;
     }

+ 3 - 1
install/sql/system.sql

@@ -1384,9 +1384,11 @@ CREATE TABLE IF NOT EXISTS `sys_sessions` (
   `user_id` int(10) unsigned NOT NULL default '0',
   `data` text,
   `date` int(10) unsigned NOT NULL default '0',
+  `ttl` int(10) unsigned NOT NULL default '0',
   PRIMARY KEY (`id`),
   KEY `user_id` (`user_id`),
-  KEY `date` (`date`)
+  KEY `date` (`date`),
+  KEY `ttl` (`ttl`)
 );