session keep alive
This commit is contained in:
@@ -1804,7 +1804,79 @@ $gridMeta = [
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sessionModal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:99999;align-items:center;justify-content:center">
|
||||
<div style="background:#fff;padding:28px 32px;border-radius:14px;max-width:420px;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,.3)">
|
||||
<h5 style="margin:0 0 10px">La sessione sta per scadere</h5>
|
||||
<p style="color:#64748b;margin:0 0 6px">Per la tua sicurezza verrai disconnesso tra</p>
|
||||
<div id="sessCountdownBig" style="font:700 34px monospace;color:#dc2626;margin:8px 0 18px">00:30</div>
|
||||
<button id="sessStayBtn" class="btn btn-primary btn-lg px-4">Resta connesso</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
// ── TEST: tempi compressi. In produzione: SESSION_MINUTES=120, WARN_SECONDS=120
|
||||
const SESSION_MINUTES = 2; // durata simulata
|
||||
const WARN_SECONDS = 30; // preavviso prima della scadenza
|
||||
const LOGIN_URL = '../login'; // adatta al tuo path reale
|
||||
|
||||
const sessionMs = SESSION_MINUTES * 60 * 1000;
|
||||
let lastActivity = Date.now();
|
||||
let modalShown = false;
|
||||
|
||||
// ogni attività reale resetta il timer locale
|
||||
['mousemove', 'keydown', 'click', 'scroll', 'touchstart'].forEach(ev =>
|
||||
document.addEventListener(ev, () => {
|
||||
lastActivity = Date.now();
|
||||
if (!modalShown) return; // se il modal è aperto, l'attività NON conta: serve il click esplicito
|
||||
}, {
|
||||
passive: true
|
||||
})
|
||||
);
|
||||
|
||||
const modal = document.getElementById('sessionModal');
|
||||
const bigCd = document.getElementById('sessCountdownBig');
|
||||
|
||||
document.getElementById('sessStayBtn').addEventListener('click', async () => {
|
||||
try {
|
||||
const r = await fetch('session_keepalive.php', {
|
||||
cache: 'no-store'
|
||||
});
|
||||
// se la sessione era già morta, headscript reindirizza: la risposta non sarà il JSON atteso
|
||||
const ct = r.headers.get('content-type') || '';
|
||||
if (!ct.includes('application/json')) {
|
||||
window.location.href = LOGIN_URL;
|
||||
return;
|
||||
}
|
||||
await r.json();
|
||||
lastActivity = Date.now(); // timer riparte
|
||||
modalShown = false;
|
||||
modal.style.display = 'none';
|
||||
} catch (e) {
|
||||
window.location.href = LOGIN_URL;
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
const elapsed = Date.now() - lastActivity;
|
||||
const remaining = Math.ceil((sessionMs - elapsed) / 1000);
|
||||
|
||||
if (remaining <= 0) {
|
||||
window.location.href = LOGIN_URL; // scaduta
|
||||
return;
|
||||
}
|
||||
if (remaining <= WARN_SECONDS && !modalShown) {
|
||||
modalShown = true;
|
||||
modal.style.display = 'flex';
|
||||
}
|
||||
if (modalShown) {
|
||||
const m = Math.floor(remaining / 60),
|
||||
s = remaining % 60;
|
||||
bigCd.textContent = String(m).padStart(2, '0') + ':' + String(s).padStart(2, '0');
|
||||
}
|
||||
}, 1000);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -56,4 +56,12 @@ $photousername = basename($avatar);
|
||||
//include files
|
||||
require_once(__DIR__ . '/../../languages/en/general.php');
|
||||
|
||||
//include("generalsettings.php");
|
||||
//include("generalsettings.php");
|
||||
|
||||
// Timbra la sessione dell'utente a ogni pagina (rolling manuale)
|
||||
try {
|
||||
$pdoSess = DBHandlerSelect::getInstance()->getConnection();
|
||||
$pdoSess->prepare("UPDATE auth_sessions SET last_activity = ? WHERE user_id = ? ORDER BY last_activity DESC LIMIT 1")
|
||||
->execute([time(), $iduserlogin]);
|
||||
} catch (\Throwable $e) { /* non bloccare la pagina */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/include/headscript.php'; // autentica e dà $iduserlogin
|
||||
require_once __DIR__ . '/class/db-functions.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
||||
$stmt = $pdo->prepare(
|
||||
"UPDATE auth_sessions SET last_activity = ? WHERE user_id = ? ORDER BY last_activity DESC LIMIT 1"
|
||||
);
|
||||
$stmt->execute([time(), $iduserlogin]);
|
||||
echo json_encode(['ok' => true, 'rows' => $stmt->rowCount(), 'ts' => time()]);
|
||||
} catch (\Throwable $e) {
|
||||
echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once __DIR__ . '/class/db-functions.php';
|
||||
$sid = session_id(); // oppure l'id Laravel, da verificare
|
||||
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
||||
$pdo->prepare("UPDATE auth_sessions SET last_activity = ? WHERE id = ?")
|
||||
->execute([time(), $sid]);
|
||||
echo json_encode(['ok' => true, 'sid' => $sid, 'ts' => time()]);
|
||||
Reference in New Issue
Block a user