包含:登录失败锁定、90天密码有效期、30分钟会话超时、 强制改密、登录审计日志、屏幕水印、企业背景图、 备案信息固定底部、favicon、登录页JS修复等全部改动
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace MRBS\Session;
|
||||
|
||||
use MRBS\SessionHandler\Cookie;
|
||||
use MRBS\User;
|
||||
use function MRBS\auth;
|
||||
use function MRBS\get_form_var;
|
||||
use function MRBS\is_ajax;
|
||||
use function MRBS\str_ends_with_array;
|
||||
use function MRBS\url_base;
|
||||
|
||||
/**
|
||||
* Uses PHP's built-in session handling.
|
||||
*/
|
||||
class SessionPhp extends SessionWithLogin
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
global $auth, $server;
|
||||
|
||||
parent::__construct();
|
||||
|
||||
// Check to see if we've been inactive for longer than allowed and if so log out the user.
|
||||
// Don't log out the user if we're in kiosk mode because the kiosk will normally be inactive.
|
||||
// Note that we cannot use is_kiosk_mode() here as that will create an infinite loop calling session().
|
||||
if (!empty($auth['session_php']['inactivity_expire_time']) && !isset($_SESSION['kiosk_password_hash']))
|
||||
{
|
||||
if (isset($_SESSION['LastActivity']) &&
|
||||
((time() - $_SESSION['LastActivity']) > $auth['session_php']['inactivity_expire_time']))
|
||||
{
|
||||
$this->logoffUser();
|
||||
}
|
||||
// Ajax requests don't count as activity, unless it's the special Ajax request used
|
||||
// to record client side activity.
|
||||
$activity = get_form_var('activity', 'int');
|
||||
if ($activity || !is_ajax() || !isset($_SESSION['LastActivity'])) {
|
||||
$_SESSION['LastActivity'] = time();
|
||||
}
|
||||
}
|
||||
|
||||
// Move the current page to the last page, so it can be used as a referrer, and store the new current page -
|
||||
// but only if (a) we are at the top level of the MRBS web directory (eg index.php) so as to eliminate all
|
||||
// the ./js, ./ajax and ./css pages and (b) this is not otherwise an Ajax request, eg one of the prefetch
|
||||
// calls to index.php.
|
||||
if (isset($server['SCRIPT_FILENAME']) && (MRBS_ROOT === dirname($server['SCRIPT_FILENAME'])) &&
|
||||
!(isset($server['HTTP_X_REQUESTED_WITH']) && ($server['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest')))
|
||||
{
|
||||
$this->updatePage($server['REQUEST_URI'] ?? $server['PHP_SELF'] ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the server has a Referrer-Policy of strict-origin then HTTP_REFERER will be unreliable
|
||||
// and it is better to use the last page that we have stored in the $_SESSION variable.
|
||||
public function getReferrer(): ?string
|
||||
{
|
||||
$result = parent::getReferrer();
|
||||
|
||||
// If the last page is known, and it's well-formed (parse_url() doesn't return false), and it's
|
||||
// not already a fully-qualified URL (ie the scheme is empty), and we've got a url base that
|
||||
// isn't the empty string, then return everything after the last '/' from the last page, prefixed
|
||||
// by the url base, in case there's a proxy in use.
|
||||
if (isset($_SESSION['last_page']))
|
||||
{
|
||||
$last_page = $_SESSION['last_page'];
|
||||
$scheme = parse_url($last_page, PHP_URL_SCHEME);
|
||||
if (($scheme === null) && ('' !== ($base = url_base())))
|
||||
{
|
||||
// Get everything after the last '/'
|
||||
$array = explode('/', $last_page);
|
||||
$result = $base . array_pop($array);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function updatePage(?string $url): void
|
||||
{
|
||||
// Don't update the page if the URL as the same as the one we've already got
|
||||
// stored for this page. This will be the case if the user has refreshed the
|
||||
// browser, and if we update the page then we'll lose the last page, which is
|
||||
// sometimes needed for MRBS to know where to go back to.
|
||||
if (isset($_SESSION['this_page']) && ($url === $_SESSION['this_page']))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$_SESSION['last_page'] = $_SESSION['this_page'] ?? null;
|
||||
$_SESSION['this_page'] = $url;
|
||||
}
|
||||
|
||||
|
||||
public function getCurrentUser() : ?User
|
||||
{
|
||||
$result = $_SESSION['user'] ?? null;
|
||||
|
||||
// For some unknown reason the integer value 0 is sometimes stored in the session
|
||||
// variable. It's not clear how this can happen.
|
||||
if (isset($result) && !(is_object($result) && is_a($result, 'MRBS\User')))
|
||||
{
|
||||
trigger_error('$_SESSION["user"] is expected to be a User object, not ' . json_encode($result), E_USER_WARNING);
|
||||
$result = null;
|
||||
}
|
||||
|
||||
return $result ?? parent::getCurrentUser();
|
||||
}
|
||||
|
||||
|
||||
protected function logonUser(string $username) : void
|
||||
{
|
||||
$user = auth()->getUser($username);
|
||||
|
||||
// As a defence against session fixation, regenerate
|
||||
// the session id and delete the old session.
|
||||
$this->regenerate();
|
||||
$_SESSION['user'] = $user;
|
||||
|
||||
// Problems have been reported on Windows IIS with session data not being
|
||||
// written out without a call to session_write_close()
|
||||
session_write_close();
|
||||
}
|
||||
|
||||
|
||||
public function logoffUser() : void
|
||||
{
|
||||
global $cookie_path_override;
|
||||
|
||||
if (ini_get("session.use_cookies"))
|
||||
{
|
||||
// Delete the session cookie
|
||||
Cookie::delete(session_name());
|
||||
|
||||
// Delete any cookies which may have previously been set, incorrectly, before the fixes to get_cookie_path (see
|
||||
// https://github.com/meeting-room-booking-system/mrbs-code/commit/90ceeb8a0bc5f4850065695a3e085114c5ecae8e and
|
||||
// https://github.com/meeting-room-booking-system/mrbs-code/commit/cb74320048149c4199281b88d50fb69988a41312).
|
||||
// Note that the problem didn't occur if $cookie_path_override was set.
|
||||
// In time, once all the incorrect cookies have expired naturally, this block can be deleted.
|
||||
if (!isset($cookie_path_override))
|
||||
{
|
||||
$params = session_get_cookie_params();
|
||||
$suffixes = array('ajax/', 'js/');
|
||||
// If the path ends with one of the suffixes we'll already have deleted it above
|
||||
if (!str_ends_with_array($params['path'], $suffixes))
|
||||
{
|
||||
foreach ($suffixes as $suffix)
|
||||
{
|
||||
setcookie(session_name(), '', time() - 42000, $params['path'] . $suffix, $params['domain'], $params['secure'], isset($params['httponly']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->destroy();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user