Quellcode durchsuchen

Long term cookie to keep session open

Token system
https://github.com/marienfressinaud/FreshRSS/issues/465
Alexandre Alapetite vor 11 Jahren
Ursprung
Commit
ee1b8f6f72
5 geänderte Dateien mit 86 neuen und 16 gelöschten Zeilen
  1. 33 8
      app/Controllers/indexController.php
  2. 25 3
      app/FreshRSS.php
  3. 1 0
      data/tokens/.gitignore
  4. 13 0
      data/tokens/index.html
  5. 14 5
      lib/Minz/Session.php

+ 33 - 8
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);
 	}
 }

+ 25 - 3
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();

+ 1 - 0
data/tokens/.gitignore

@@ -0,0 +1 @@
+*.txt

+ 13 - 0
data/tokens/index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB">
+<head>
+<meta charset="UTF-8" />
+<meta http-equiv="Refresh" content="0; url=/" />
+<title>Redirection</title>
+<meta name="robots" content="noindex" />
+</head>
+
+<body>
+<p><a href="/">Redirection</a></p>
+</body>
+</html>

+ 14 - 5
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;
+	}
+
 }