Simplify session handling #39

Merged
Roflin merged 2 commits from simplify-sessions into master 2023-11-22 16:03:40 +01:00
2 changed files with 34 additions and 42 deletions

View File

@ -11,7 +11,7 @@ class Logout extends HTMLController
public function __construct() public function __construct()
{ {
// Clear the entire sesssion. // Clear the entire sesssion.
$_SESSION = []; Session::clear();
// Back to the frontpage you go. // Back to the frontpage you go.
header('Location: ' . BASEURL); header('Location: ' . BASEURL);

View File

@ -3,47 +3,55 @@
* Session.php * Session.php
* Contains the key class Session. * Contains the key class Session.
* *
* Kabuki CMS (C) 2013-2015, Aaron van Geffen * Kabuki CMS (C) 2013-2023, Aaron van Geffen
*****************************************************************************/ *****************************************************************************/
class Session class Session
{ {
public static function clear()
{
$_SESSION = [];
}
public static function start() public static function start()
{ {
session_start(); session_start();
// Resuming an existing session? Check what we know! if (!isset($_SESSION['session_token_key'], $_SESSION['session_token']))
if (isset($_SESSION['user_id'], $_SESSION['ip_address'], $_SESSION['user_agent'])) self::generateSessionToken();
{
// If we're not browsing over HTTPS, protect against session hijacking.
if (!isset($_SERVER['HTTPS']) && isset($_SERVER['REMOTE_ADDR']) && $_SESSION['ip_address'] !== $_SERVER['REMOTE_ADDR'])
{
$_SESSION = [];
Dispatcher::kickGuest('Your session failed to validate', 'Your IP address has changed. Please re-login and try again.');
}
// Either way, require re-login if the browser identifier has changed.
elseif (isset($_SERVER['HTTP_USER_AGENT']) && $_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT'])
{
$_SESSION = [];
Dispatcher::kickGuest('Your session failed to validate', 'Your browser identifier has changed. Please re-login and try again.');
}
}
elseif (!isset($_SESSION['ip_address'], $_SESSION['user_agent']))
$_SESSION = [
'ip_address' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '',
];
return true; return true;
} }
public static function resetSessionToken() public static function generateSessionToken()
{ {
$_SESSION['session_token'] = sha1(session_id() . mt_rand()); $_SESSION['session_token'] = sha1(session_id() . mt_rand());
$_SESSION['session_token_key'] = substr(preg_replace('~^\d+~', '', sha1(mt_rand() . session_id() . mt_rand())), 0, rand(7, 12)); $_SESSION['session_token_key'] = substr(preg_replace('~^\d+~', '', sha1(mt_rand() . session_id() . mt_rand())), 0, rand(7, 12));
return true; return true;
} }
public static function getSessionToken()
{
if (empty($_SESSION['session_token']))
trigger_error('Call to getSessionToken without a session token being set!', E_USER_ERROR);
return $_SESSION['session_token'];
}
public static function getSessionTokenKey()
{
if (empty($_SESSION['session_token_key']))
trigger_error('Call to getSessionTokenKey without a session token key being set!', E_USER_ERROR);
return $_SESSION['session_token_key'];
}
public static function resetSessionToken()
{
// Old interface; now always true.
return true;
}
public static function validateSession($method = 'post') public static function validateSession($method = 'post')
{ {
// First, check whether the submitted token and key match the ones in storage. // First, check whether the submitted token and key match the ones in storage.
@ -67,23 +75,7 @@ class Session
throw new UserFacingException('Invalid referring URL. Please reload the page and try again.'); throw new UserFacingException('Invalid referring URL. Please reload the page and try again.');
} }
// All looks good from here! But you can only use this token once, so... // All looks good from here!
return self::resetSessionToken(); return true;
}
public static function getSessionToken()
{
if (empty($_SESSION['session_token']))
trigger_error('Call to getSessionToken without a session token being set!', E_USER_ERROR);
return $_SESSION['session_token'];
}
public static function getSessionTokenKey()
{
if (empty($_SESSION['session_token_key']))
trigger_error('Call to getSessionTokenKey without a session token key being set!', E_USER_ERROR);
return $_SESSION['session_token_key'];
} }
} }