From eceb7756cfcf117c2a18984291181a84697ed3cd Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 10 Aug 2014 20:29:43 +0200 Subject: Add possibility to keep logged in with form Add an option to keep logged in. Change lifetime of session cookie to 1 year. See https://github.com/marienfressinaud/FreshRSS/issues/465 --- lib/Minz/Session.php | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'lib/Minz/Session.php') diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index ddabc4658..c859be2ed 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -15,13 +15,15 @@ class Minz_Session { * Le nom de session est utilisé comme nom pour les cookies et les URLs (i.e. PHPSESSID). * Il ne doit contenir que des caractères alphanumériques ; il doit être court et descriptif */ - public static function init ($name) { + public static function init($name) { + $cookie = session_get_cookie_params(); + self::keepCookie($cookie['lifetime']); + // démarre la session - session_name ($name); - session_set_cookie_params (0, dirname(empty($_SERVER['REQUEST_URI']) ? '/' : dirname($_SERVER['REQUEST_URI'])), null, false, true); - session_start (); + session_name($name); + session_start(); - if (isset ($_SESSION)) { + if (isset($_SESSION)) { self::$session = $_SESSION; } } @@ -68,4 +70,27 @@ class Minz_Session { Minz_Translate::reset (); } } + + + /** + * Spécifie la durée de vie des cookies + * @param $l la durée de vie + */ + public static function keepCookie($l) { + $cookie_dir = dirname( + empty($_SERVER['SCRIPT_NAME']) ? '' : $_SERVER['SCRIPT_NAME'] + ) . '/'; + session_set_cookie_params($l, $cookie_dir, $_SERVER['HTTP_HOST'], + false, true); + } + + + /** + * Régénère un id de session. + * Utile pour appeler session_set_cookie_params après session_start() + */ + public static function regenerateID() { + session_regenerate_id(true); + } + } -- cgit v1.2.3 From df47217839ccddb8e03015959c61b61e748d9700 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 10 Aug 2014 23:41:36 +0200 Subject: Set session.gc_maxlifetime Take the maxvalue between 1440 (24m) and cookie lifetime when calling Minz_Session::keepCookie() See https://github.com/marienfressinaud/FreshRSS/issues/465 --- lib/Minz/Session.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/Minz/Session.php') diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index c859be2ed..fb3c5d74b 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -82,6 +82,9 @@ class Minz_Session { ) . '/'; session_set_cookie_params($l, $cookie_dir, $_SERVER['HTTP_HOST'], false, true); + + $l_session = max(1440, $l); + ini_set('session.gc_maxlifetime', $l_session); } -- cgit v1.2.3 From bc71a577fe3154080df9949b394c7ae552773c7b Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Mon, 11 Aug 2014 18:39:22 +0200 Subject: Revert "Set session.gc_maxlifetime" This reverts commit df47217839ccddb8e03015959c61b61e748d9700. See https://github.com/marienfressinaud/FreshRSS/issues/465 --- lib/Minz/Session.php | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib/Minz/Session.php') diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index fb3c5d74b..c859be2ed 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -82,9 +82,6 @@ class Minz_Session { ) . '/'; session_set_cookie_params($l, $cookie_dir, $_SERVER['HTTP_HOST'], false, true); - - $l_session = max(1440, $l); - ini_set('session.gc_maxlifetime', $l_session); } -- cgit v1.2.3 From ed7d8aa44fe5a005380056b7d164fc53079506fb Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Tue, 12 Aug 2014 21:04:39 +0200 Subject: Use REQUEST_URI instead of SCRIPT_NAME for cookies See https://github.com/marienfressinaud/FreshRSS/commit/eceb7756cfcf117c2a18984291181a84697ed3cd#commitcomment-7345438 --- lib/Minz/Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Minz/Session.php') diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index c859be2ed..efc8332e5 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -78,7 +78,7 @@ class Minz_Session { */ public static function keepCookie($l) { $cookie_dir = dirname( - empty($_SERVER['SCRIPT_NAME']) ? '' : $_SERVER['SCRIPT_NAME'] + empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI'] ) . '/'; session_set_cookie_params($l, $cookie_dir, $_SERVER['HTTP_HOST'], false, true); -- cgit v1.2.3 From 08a9009c19b2ae84555340622c344a2da38ae019 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Tue, 12 Aug 2014 21:09:13 +0200 Subject: Fix a Minz_Session TODO Not use additional variable to manipulate session variables Fix coding style --- lib/Minz/Session.php | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'lib/Minz/Session.php') diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index efc8332e5..906acc03c 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -2,17 +2,11 @@ /** * La classe Session gère la session utilisateur - * C'est un singleton */ class Minz_Session { - /** - * $session stocke les variables de session - */ - private static $session = array (); //TODO: Try to avoid having another local copy - /** * Initialise la session, avec un nom - * Le nom de session est utilisé comme nom pour les cookies et les URLs (i.e. PHPSESSID). + * Le nom de session est utilisé comme nom pour les cookies et les URLs(i.e. PHPSESSID). * Il ne doit contenir que des caractères alphanumériques ; il doit être court et descriptif */ public static function init($name) { @@ -22,10 +16,6 @@ class Minz_Session { // démarre la session session_name($name); session_start(); - - if (isset($_SESSION)) { - self::$session = $_SESSION; - } } @@ -34,8 +24,8 @@ class Minz_Session { * @param $p le paramètre à récupérer * @return la valeur de la variable de session, false si n'existe pas */ - public static function param ($p, $default = false) { - return isset(self::$session[$p]) ? self::$session[$p] : $default; + public static function param($p, $default = false) { + return isset($_SESSION[$p]) ? $_SESSION[$p] : $default; } @@ -44,13 +34,11 @@ class Minz_Session { * @param $p le paramètre à créer ou modifier * @param $v la valeur à attribuer, false pour supprimer */ - public static function _param ($p, $v = false) { + public static function _param($p, $v = false) { if ($v === false) { - unset ($_SESSION[$p]); - unset (self::$session[$p]); + unset($_SESSION[$p]); } else { $_SESSION[$p] = $v; - self::$session[$p] = $v; } } @@ -59,15 +47,15 @@ class Minz_Session { * Permet d'effacer une session * @param $force si à false, n'efface pas le paramètre de langue */ - public static function unset_session ($force = false) { - $language = self::param ('language'); + public static function unset_session($force = false) { + $language = self::param('language'); session_destroy(); - self::$session = array (); + $_SESSION = array(); if (!$force) { - self::_param ('language', $language); - Minz_Translate::reset (); + self::_param('language', $language); + Minz_Translate::reset(); } } -- cgit v1.2.3 From ee1b8f6f72e8c2cbd3e0ad7b4322a4bb6863c028 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Aug 2014 00:09:48 +0200 Subject: Long term cookie to keep session open Token system https://github.com/marienfressinaud/FreshRSS/issues/465 --- app/Controllers/indexController.php | 41 +++++++++++++++++++++++++++++-------- app/FreshRSS.php | 28 ++++++++++++++++++++++--- data/tokens/.gitignore | 1 + data/tokens/index.html | 13 ++++++++++++ lib/Minz/Session.php | 19 ++++++++++++----- 5 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 data/tokens/.gitignore create mode 100644 data/tokens/index.html (limited to 'lib/Minz/Session.php') diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index b907c8eed..dd5b91e47 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -295,10 +295,39 @@ class FreshRSS_index_Controller extends Minz_ActionController { Minz_Session::_param('passwordHash'); } + private static function makeLongTermCookie($username, $passwordHash) { + do { + $token = sha1(Minz_Configuration::salt() . $username . uniqid(mt_rand(), true)); + $tokenFile = DATA_PATH . '/tokens/' . $token . '.txt'; + } while (file_exists($tokenFile)); + if (@file_put_contents($tokenFile, $username . "\t" . $passwordHash) === false) { + return false; + } + $expire = time() + 2629744; //1 month //TODO: Use a configuration instead + Minz_Session::setLongTermCookie('FreshRSS_login', $token, $expire); + Minz_Session::_param('token', $token); + return $token; + } + + private static function deleteLongTermCookie() { + Minz_Session::deleteLongTermCookie('FreshRSS_login'); + $token = Minz_Session::param('token', null); + if (ctype_alnum($token)) { + @unlink(DATA_PATH . '/tokens/' . $token . '.txt'); + } + Minz_Session::_param('token'); + if (rand(0, 10) === 1) { + self::purgeTokens(); + } + } + + private static function purgeTokens() { + //TODO: Delete old token files + } + public function formLoginAction () { if (Minz_Request::isPost()) { $ok = false; - $keep_logged_in = Minz_Request::param('keep_logged_in', false); $nonce = Minz_Session::param('nonce'); $username = Minz_Request::param('username', ''); $c = Minz_Request::param('challenge', ''); @@ -313,10 +342,8 @@ class FreshRSS_index_Controller extends Minz_ActionController { if ($ok) { Minz_Session::_param('currentUser', $username); Minz_Session::_param('passwordHash', $s); - if ($keep_logged_in) { - // New cookie with a lifetime of 1 month. - Minz_Session::keepCookie(2592000); - Minz_Session::regenerateID(); + if (Minz_Request::param('keep_logged_in', false)) { + self::makeLongTermCookie($username, $s); } } else { Minz_Log::record('Password mismatch for user ' . $username . ', nonce=' . $nonce . ', c=' . $c, Minz_Log::WARNING); @@ -377,9 +404,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { Minz_Session::_param('currentUser'); Minz_Session::_param('mail'); Minz_Session::_param('passwordHash'); - Minz_Session::keepCookie(0); - Minz_Session::regenerateID(); - + self::deleteLongTermCookie(); Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); } } diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 7c333b090..30f711e20 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -20,13 +20,35 @@ class FreshRSS extends Minz_FrontController { $this->loadNotifications(); } + private static function getCredentialsFromLongTermCookie() { + $token = Minz_Session::getLongTermCookie('FreshRSS_login'); + if (!ctype_alnum($token)) { + return array(); + } + $tokenFile = DATA_PATH . '/tokens/' . $token . '.txt'; + $mtime = @filemtime($tokenFile); + if ($mtime + 2629744 < time()) { //1 month //TODO: Use a configuration instead + @unlink($tokenFile); + return array(); //Expired or token does not exist + } + $credentials = @file_get_contents($tokenFile); + return $credentials === false ? array() : explode("\t", $credentials, 2); + } + private function accessControl($currentUser) { if ($currentUser == '') { switch (Minz_Configuration::authType()) { case 'form': - $currentUser = Minz_Configuration::defaultUser(); - Minz_Session::_param('passwordHash'); - $loginOk = false; + $credentials = self::getCredentialsFromLongTermCookie(); + if (isset($credentials[1])) { + $currentUser = trim($credentials[0]); + Minz_Session::_param('passwordHash', trim($credentials[1])); + } + $loginOk = $currentUser != ''; + if (!$loginOk) { + $currentUser = Minz_Configuration::defaultUser(); + Minz_Session::_param('passwordHash'); + } break; case 'http_auth': $currentUser = httpAuthUser(); diff --git a/data/tokens/.gitignore b/data/tokens/.gitignore new file mode 100644 index 000000000..2211df63d --- /dev/null +++ b/data/tokens/.gitignore @@ -0,0 +1 @@ +*.txt diff --git a/data/tokens/index.html b/data/tokens/index.html new file mode 100644 index 000000000..85faaa37e --- /dev/null +++ b/data/tokens/index.html @@ -0,0 +1,13 @@ + + + + + +Redirection + + + + +

Redirection

+ + diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php index 906acc03c..af4de75bb 100644 --- a/lib/Minz/Session.php +++ b/lib/Minz/Session.php @@ -65,11 +65,8 @@ class Minz_Session { * @param $l la durée de vie */ public static function keepCookie($l) { - $cookie_dir = dirname( - empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI'] - ) . '/'; - session_set_cookie_params($l, $cookie_dir, $_SERVER['HTTP_HOST'], - false, true); + $cookie_dir = empty($_SERVER['REQUEST_URI']) ? '' : $_SERVER['REQUEST_URI']; + session_set_cookie_params($l, $cookie_dir, '', false, true); } @@ -81,4 +78,16 @@ class Minz_Session { session_regenerate_id(true); } + public static function deleteLongTermCookie($name) { + setcookie($name, '', 1, '', '', false, true); + } + + public static function setLongTermCookie($name, $value, $expire) { + setcookie($name, $value, $expire, '', '', false, true); + } + + public static function getLongTermCookie($name) { + return isset($_COOKIE[$name]) ? $_COOKIE[$name] : null; + } + } -- cgit v1.2.3