Start every session through session.php; idle timeout, app access and auth status codes
This commit is contained in:
+49
-2
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
// app/session.php
|
||||
// Every page and API engine starts its session through this file, so the cookie
|
||||
// flags and the idle timeout below apply to the whole app, not only the login routes.
|
||||
ob_start(); // ensure output buffering is on regardless of php.ini — prevents stray output from corrupting JSON API responses
|
||||
|
||||
// The buffer is still flushed, so notices would still land in front of the JSON
|
||||
@@ -8,6 +10,11 @@ ob_start(); // ensure output buffering is on regardless of php.ini — prevents
|
||||
ini_set('display_errors', '0');
|
||||
ini_set('log_errors', '1');
|
||||
|
||||
// Signed-in sessions end after this many seconds without a request.
|
||||
if (!defined('SESSION_IDLE_SECONDS')) {
|
||||
define('SESSION_IDLE_SECONDS', 1800);
|
||||
}
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
|
||||
// Derive cookie path dynamically from the current script location.
|
||||
@@ -20,7 +27,12 @@ if (session_status() === PHP_SESSION_NONE) {
|
||||
$parts = explode('/', trim($_SERVER['SCRIPT_NAME'], '/'));
|
||||
$repo_name = '/' . $parts[0] . '/'; // e.g. /wms/
|
||||
|
||||
// HTTPS directly, or TLS terminated by a reverse proxy in front of Apache.
|
||||
$is_https = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
|
||||
|| strtolower($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https';
|
||||
|
||||
ini_set('session.use_strict_mode', 1);
|
||||
ini_set('session.use_only_cookies', 1);
|
||||
ini_set('session.gc_maxlifetime', 3600);
|
||||
ini_set('session.cookie_path', $repo_name);
|
||||
ini_set('session.cookie_httponly', 1);
|
||||
@@ -29,9 +41,44 @@ if (session_status() === PHP_SESSION_NONE) {
|
||||
'lifetime' => 0,
|
||||
'path' => $repo_name,
|
||||
'domain' => '',
|
||||
'secure' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
||||
'secure' => $is_https,
|
||||
'httponly' => true,
|
||||
'samesite' => 'Lax',
|
||||
]);
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Idle timeout: a signed-in session untouched for SESSION_IDLE_SECONDS is
|
||||
// cleared here, so pages redirect to the login form and API engines answer
|
||||
// 401 (db_auth.php) exactly as for a visitor who never signed in.
|
||||
if (!empty($_SESSION['login_company_id'])) {
|
||||
$last = (int)($_SESSION['_last_activity'] ?? 0);
|
||||
if ($last > 0 && (time() - $last) > SESSION_IDLE_SECONDS) {
|
||||
$_SESSION = [];
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['_idle_expired'] = true;
|
||||
} else {
|
||||
$_SESSION['_last_activity'] = time();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End the current session completely: server data, the session file and the
|
||||
* browser cookie. Used by logout and by any flow that must force a new sign-in.
|
||||
*/
|
||||
if (!function_exists('session_end_completely')) {
|
||||
function session_end_completely(): void {
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) return;
|
||||
$_SESSION = [];
|
||||
$p = session_get_cookie_params();
|
||||
setcookie(session_name(), '', [
|
||||
'expires' => time() - 42000,
|
||||
'path' => $p['path'],
|
||||
'domain' => $p['domain'],
|
||||
'secure' => $p['secure'],
|
||||
'httponly' => $p['httponly'],
|
||||
'samesite' => $p['samesite'] ?? 'Lax',
|
||||
]);
|
||||
session_destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user