diff --git a/ChangeLog b/ChangeLog index 991f4b4e07..0456555691 100644 --- a/ChangeLog +++ b/ChangeLog @@ -76,6 +76,7 @@ phpMyAdmin - ChangeLog - issue #12976 Improved foreign key editor behavior - issue #12958 Always show error reporting dialog on top - issue #12693 Improved support for TokuDB +- issue #11231 Try harder to honor LoginCookieValidity setting 4.6.6 (2017-01-23) - issue #12759 Fix Notice regarding 'Undefined index: old_usergroup' diff --git a/js/functions.js b/js/functions.js index 9c662c7620..afbb09683f 100644 --- a/js/functions.js +++ b/js/functions.js @@ -918,17 +918,31 @@ AJAX.registerOnload('functions.js', function () { document.onkeypress = function() { _idleSecondsCounter = 0; }; + function guid() { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + + s4() + '-' + s4() + s4() + s4(); + } function SetIdleTime() { _idleSecondsCounter++; } function UpdateIdleTime() { var href = 'index.php'; + var guid = 'default'; + if (isStorageSupported('sessionStorage')) { + guid = window.sessionStorage.guid; + } var params = { 'ajax_request' : true, 'token' : PMA_commonParams.get('token'), 'server' : PMA_commonParams.get('server'), 'db' : PMA_commonParams.get('db'), + 'guid': guid, 'access_time':_idleSecondsCounter }; $.ajax({ @@ -937,17 +951,24 @@ AJAX.registerOnload('functions.js', function () { data: params, success: function (data) { if (data.success) { - var remaining = PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter; + if (PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter < 0) { + /* There is other active window, let's reset counter */ + _idleSecondsCounter = 0; + } + var remaining = Math.min( + /* Remaining login validity */ + PMA_commonParams.get('LoginCookieValidity') - _idleSecondsCounter, + /* Remaining time till session GC */ + PMA_commonParams.get('session_gc_maxlifetime') + ); + var interval = 1000; if (remaining > 5) { // max value for setInterval() function - var interval = Math.min(remaining * 1000, Math.pow(2, 31) - 1); - updateTimeout = window.setTimeout(UpdateIdleTime, interval); - } else if (remaining > 0) { - // We're close to session expiry - updateTimeout = window.setTimeout(UpdateIdleTime, 2000); + interval = Math.min((remaining - 1) * 1000, Math.pow(2, 31) - 1); } + updateTimeout = window.setTimeout(UpdateIdleTime, interval); } else { //timeout occurred - if(isStorageSupported('sessionStorage')){ + if (isStorageSupported('sessionStorage')){ window.sessionStorage.clear(); } window.location.reload(true); @@ -958,7 +979,14 @@ AJAX.registerOnload('functions.js', function () { } if (PMA_commonParams.get('logged_in') && PMA_commonParams.get('auth_type') == 'cookie') { IncInterval = window.setInterval(SetIdleTime, 1000); - var interval = (PMA_commonParams.get('LoginCookieValidity') - 5) * 1000; + var session_timeout = Math.min( + PMA_commonParams.get('LoginCookieValidity'), + PMA_commonParams.get('session_gc_maxlifetime') + ); + if (isStorageSupported('sessionStorage')) { + window.sessionStorage.setItem('guid', guid()); + } + var interval = (session_timeout - 5) * 1000; if (interval > Math.pow(2, 31) - 1) { // max value for setInterval() function interval = Math.pow(2, 31) - 1; } diff --git a/libraries/Header.php b/libraries/Header.php index 4f608f4e87..5f49e269a6 100644 --- a/libraries/Header.php +++ b/libraries/Header.php @@ -252,6 +252,7 @@ class Header 'pftext' => $pftext, 'confirm' => $GLOBALS['cfg']['Confirm'], 'LoginCookieValidity' => $GLOBALS['cfg']['LoginCookieValidity'], + 'session_gc_maxlifetime' => (int)@ini_get('session.gc_maxlifetime'), 'logged_in' => isset($GLOBALS['userlink']) ? true : false, 'PMA_VERSION' => PMA_VERSION ); diff --git a/libraries/plugins/AuthenticationPlugin.php b/libraries/plugins/AuthenticationPlugin.php index 630610f286..479b06d51a 100644 --- a/libraries/plugins/AuthenticationPlugin.php +++ b/libraries/plugins/AuthenticationPlugin.php @@ -145,17 +145,23 @@ abstract class AuthenticationPlugin * * @return void */ - public function setSessionAccessTime() - { + public function setSessionAccessTime() + { + if (isset($_REQUEST['guid'])) { + $guid = (string)$_REQUEST['guid']; + } else { + $guid = 'default'; + } if (isset($_REQUEST['access_time'])) { // Ensure access_time is in range <0, LoginCookieValidity + 1> // to avoid excessive extension of validity. // // Negative values can cause session expiry extension // Too big values can cause overflow and lead to same - $_SESSION['last_access_time'] = time() - min(max(0, intval($_REQUEST['access_time'])), $GLOBALS['cfg']['LoginCookieValidity'] + 1); + $time = time() - min(max(0, intval($_REQUEST['access_time'])), $GLOBALS['cfg']['LoginCookieValidity'] + 1); } else { - $_SESSION['last_access_time'] = time(); + $time = time(); } + $_SESSION['browser_access_time'][$guid] = $time; } } diff --git a/libraries/plugins/auth/AuthenticationCookie.php b/libraries/plugins/auth/AuthenticationCookie.php index 8a444d6c4a..a26152fcca 100644 --- a/libraries/plugins/auth/AuthenticationCookie.php +++ b/libraries/plugins/auth/AuthenticationCookie.php @@ -379,13 +379,19 @@ class AuthenticationCookie extends AuthenticationPlugin ); // user was never logged in since session start - if (empty($_SESSION['last_access_time'])) { + if (empty($_SESSION['browser_access_time'])) { return false; } // User inactive too long $last_access_time = time() - $GLOBALS['cfg']['LoginCookieValidity']; - if ($_SESSION['last_access_time'] < $last_access_time) { + foreach ($_SESSION['browser_access_time'] as $key => $value) { + if ($value < $last_access_time) { + unset($_SESSION['browser_access_time'][$key]); + } + } + // All sessions expired + if (empty($_SESSION['browser_access_time'])) { Util::cacheUnset('is_create_db_priv'); Util::cacheUnset('is_reload_priv'); Util::cacheUnset('db_to_create'); diff --git a/test/classes/plugin/auth/AuthenticationCookieTest.php b/test/classes/plugin/auth/AuthenticationCookieTest.php index 1a37db1587..1b5bffb686 100644 --- a/test/classes/plugin/auth/AuthenticationCookieTest.php +++ b/test/classes/plugin/auth/AuthenticationCookieTest.php @@ -562,7 +562,7 @@ class AuthenticationCookieTest extends PMATestCase $GLOBALS['cfg']['blowfish_secret'] = 'secret'; $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = ''; $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; - $_SESSION['last_access_time'] = time() - 1000; + $_SESSION['browser_access_time']['default'] = time() - 1000; $GLOBALS['cfg']['LoginCookieValidity'] = 1440; // mock for blowfish function @@ -608,7 +608,7 @@ class AuthenticationCookieTest extends PMATestCase $GLOBALS['cfg']['CaptchaLoginPrivateKey'] = ''; $GLOBALS['cfg']['CaptchaLoginPublicKey'] = ''; $GLOBALS['cfg']['LoginCookieValidity'] = 0; - $_SESSION['last_access_time'] = -1; + $_SESSION['browser_access_time']['default'] = -1; // mock for blowfish function $this->object = $this->getMockBuilder('PMA\libraries\plugins\auth\AuthenticationCookie') ->disableOriginalConstructor()