diff options
author | Simon Rettberg | 2021-05-04 17:32:26 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-05-11 14:50:11 +0200 |
commit | 1e8329986ef4d06a9bb7550e24f4dacc7715fb5b (patch) | |
tree | 67e13b41650992d2266d42c88b91489a65840eae /inc/session.inc.php | |
parent | [systemstatus] Fix displaying VM store usage if using internal storage (diff) | |
download | slx-admin-1e8329986ef4d06a9bb7550e24f4dacc7715fb5b.tar.gz slx-admin-1e8329986ef4d06a9bb7550e24f4dacc7715fb5b.tar.xz slx-admin-1e8329986ef4d06a9bb7550e24f4dacc7715fb5b.zip |
[main+Session] Move session from /tmp/ to session table
Diffstat (limited to 'inc/session.inc.php')
-rw-r--r-- | inc/session.inc.php | 133 |
1 files changed, 82 insertions, 51 deletions
diff --git a/inc/session.inc.php b/inc/session.inc.php index cb52cd38..f06cd580 100644 --- a/inc/session.inc.php +++ b/inc/session.inc.php @@ -2,18 +2,17 @@ require_once('config.php'); -@mkdir(CONFIG_SESSION_DIR, 0700, true); -@chmod(CONFIG_SESSION_DIR, 0700); -if (!is_writable(CONFIG_SESSION_DIR)) die('Config error: Session Path not writable!'); - class Session { private static $sid = false; private static $data = false; + private static $dataChanged = false; + private static $userId = 0; - private static function generateSessionId($salt) + private static function generateSessionId(string $salt) { - if (self::$sid !== false) Util::traceError('Error: Asked to generate session id when already set.'); + if (self::$sid !== false) + Util::traceError('Error: Asked to generate session id when already set.'); self::$sid = sha1($salt . ',' . mt_rand(0, 65535) . $_SERVER['REMOTE_ADDR'] @@ -27,26 +26,40 @@ class Session ); } - public static function create($salt = '') + public static function create(string $salt, int $userId, bool $fixedAddress) { self::generateSessionId($salt); - self::$data = array(); + self::$data = []; + self::$userId = $userId; + Database::exec("INSERT INTO session (sid, userid, dateline, lastip, fixedip, data) + VALUES (:sid, :userid, 0, '', :fixedip, '')", [ + 'sid' => self::$sid, + 'userid' => $userId, + 'fixedip' => $fixedAddress ? 1 : 0, + ]); } - public static function load() + public static function load(): bool { // Try to load session id from cookie - if (!self::loadSessionId()) return false; + if (!self::loadSessionId()) + return false; // Succeeded, now try to load session data. If successful, job is done - if (self::readSessionData()) return true; + if (self::readSessionData()) + return true; // Loading session data failed - self::delete(); return false; } - public static function get($key) + public static function getUserId(): int + { + return self::$userId; + } + + public static function get(string $key) { - if (!isset(self::$data[$key]) || !is_array(self::$data[$key])) return false; + if (!isset(self::$data[$key]) || !is_array(self::$data[$key])) + return false; return self::$data[$key][0]; } @@ -55,30 +68,37 @@ class Session * @param mixed $value data to store for key, false = delete * @param int|false $validMinutes validity in minutes, or false = forever */ - public static function set($key, $value, $validMinutes = false) + public static function set(string $key, $value, $validMinutes = 60) { - if (self::$data === false) Util::traceError('Tried to set session data with no active session'); + if (self::$data === false) + Util::traceError('Tried to set session data with no active session'); if ($value === false) { unset(self::$data[$key]); } else { self::$data[$key] = [$value, $validMinutes === false ? false : time() + $validMinutes * 60]; } + self::$dataChanged = true; } - private static function loadSessionId() + private static function loadSessionId(): bool { - if (self::$sid !== false) die('Error: Asked to load session id when already set.'); - if (empty($_COOKIE['sid'])) return false; + if (self::$sid !== false) + Util::traceError('Error: Asked to load session id when already set.'); + if (empty($_COOKIE['sid'])) + return false; $id = preg_replace('/[^a-zA-Z0-9]/', '', $_COOKIE['sid']); - if (empty($id)) return false; + if (empty($id)) + return false; self::$sid = $id; return true; } public static function delete() { - if (self::$sid === false) return; - @unlink(self::getSessionFile()); + if (self::$sid === false) + return; + Database::exec("DELETE FROM session WHERE sid = :sid", + ['sid' => self::$sid]); self::deleteCookie(); self::$sid = false; self::$data = false; @@ -88,47 +108,58 @@ class Session { Util::clearCookie('sid'); } - - private static function getSessionFile() - { - if (self::$sid === false) Util::traceError('Error: Tried to access session file when no session id was set.'); - return CONFIG_SESSION_DIR . '/' . self::$sid; - } - private static function readSessionData() + private static function readSessionData(): bool { - if (self::$data !== false) Util::traceError('Tried to call read session data twice'); - $sessionfile = self::getSessionFile(); - if (!is_readable($sessionfile) || filemtime($sessionfile) + CONFIG_SESSION_TIMEOUT < time()) { - @unlink($sessionfile); - return false; - } - self::$data = @unserialize(@file_get_contents($sessionfile)); - if (self::$data === false) - return false; + if (self::$data !== false) + Util::traceError('Tried to call read session data twice'); + $row = Database::queryFirst("SELECT userid, dateline, lastip, fixedip, data FROM session WHERE sid = :sid", + ['sid' => self::$sid]); $now = time(); - $save = false; + if ($row === false || $row['dateline'] < $now) { + self::delete(); + return false; + } + if ($row['fixedip'] && $row['lastip'] !== $_SERVER['REMOTE_ADDR']) { + return false; // Ignore but don't invalidate + } + self::$userId = $row['userid']; + self::$data = @json_decode($row['data'], true); + if (!is_array(self::$data)) { + self::$data = []; + } foreach (array_keys(self::$data) as $key) { if (self::$data[$key][1] !== false && self::$data[$key][1] < $now) { unset(self::$data[$key]); - $save = true; + self::$dataChanged = true; } } - if ($save) { - self::save(); - } return true; } - public static function save() + public static function saveInternal() { - if (self::$sid === false || self::$data === false) return; //Util::traceError('Called saveSession with no active session'); - $sessionfile = self::getSessionFile(); - $ret = @file_put_contents($sessionfile, @serialize(self::$data)); - if (!$ret) Util::traceError('Storing session data in ' . $sessionfile . ' failed.'); - Util::clearCookie('sid'); - $ret = setcookie('sid', self::$sid, time() + CONFIG_SESSION_TIMEOUT, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true); - if (!$ret) Util::traceError('Error: Could not set Cookie for Client (headers already sent)'); + $now = time(); + $args = [ + 'dateline' => $now + CONFIG_SESSION_TIMEOUT, + 'lastip' => $_SERVER['REMOTE_ADDR'], + ]; + if (self::$dataChanged) { + $args['data'] = json_encode(self::$data); + } + $query = "UPDATE session SET " . implode(', ', array_map(function ($key) { + return "$key = :$key"; + }, array_keys($args))) . " WHERE sid = :sid"; + $args['sid'] = self::$sid; + Database::exec($query, $args); + $ret = setcookie('sid', self::$sid, $now + CONFIG_SESSION_TIMEOUT, + null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true); + if (!$ret) + Util::traceError('Error: Could not set Cookie for Client (headers already sent)'); } + } +register_shutdown_function(function () { + Session::saveInternal(); +}); |