mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-10-01 23:15:28 -04:00
fix: only store sessions for clients that carry them
Every request through index.php starts a session and always dirties it: zm_session_set_remote_addr() writes remoteAddr, and index.php stores skin, css and navbar_type. ZMSessionHandler::write() then persisted that session unconditionally, so any request arriving without a ZMSESSID cookie left a Sessions row behind that nothing would ever load again. Viewing an event polls the event's server every ZM_WEB_REFRESH_STATUS seconds via monitorUrl, which is absolute when the monitor has a Server row. Those cross-origin ajax polls carry auth in the URL and no cookie, so each one added a Sessions row every few seconds. Bot scans of the login page did the same. Persist a session only when the client presented our cookie, or when zm_session_persist() marks it as one we are issuing: login, and the postLoginQuery stashed before redirecting to the login page. Verified on a live install by logging row counts from the save handler: three cookieless requests skipped the write and left the count unchanged, while a cookie-jar run wrote on the request that returned the cookie. php -l clean on both files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GAFKf86P78WqniPEP2b45J
This commit is contained in:
1 parent
030a56f8db
commit
712994b196
2 files changed
+24
No files matched your search
@@ -40,6 +40,26 @@ function zm_setcookie($cookie, $value, $options=array()) {
|
||||
//ZM\Debug("Setting cookie for $cookie to $value");
|
||||
}
|
||||
|
||||
// A session is only worth storing if the client actually carries it. A request
|
||||
// that arrives without our cookie - a bot, an image tag or a cross-origin ajax
|
||||
// poll authenticated by auth hash or token - still gets a session for the life
|
||||
// of the request, but writing it out leaves a Sessions row that nothing will
|
||||
// ever load again. Viewing an event polls the event's server every
|
||||
// ZM_WEB_REFRESH_STATUS seconds, so a cross-origin poll used to add a row every
|
||||
// few seconds. Login is the exception: that is where a session is first issued.
|
||||
$zm_session_persist = false;
|
||||
|
||||
// Store this session even though the client arrived without our cookie.
|
||||
function zm_session_persist() {
|
||||
global $zm_session_persist;
|
||||
$zm_session_persist = true;
|
||||
}
|
||||
|
||||
function zm_session_is_persistable() {
|
||||
global $zm_session_persist;
|
||||
return $zm_session_persist || !empty($_COOKIE[session_name()]);
|
||||
}
|
||||
|
||||
// ZM session start function support timestamp management
|
||||
function zm_session_start() {
|
||||
if (ini_get('session.name') != 'ZMSESSID') {
|
||||
@@ -115,6 +135,8 @@ function zm_session_regenerate_id() {
|
||||
// Assumes zm_session_start() has been called previously.
|
||||
function zm_session_regenerate_id_login() {
|
||||
if (!is_session_started()) zm_session_start();
|
||||
// The client has no cookie yet on a first login, but this session must be stored.
|
||||
zm_session_persist();
|
||||
// Discard any pre-auth session contents so nothing carries across the
|
||||
// authentication boundary.
|
||||
$_SESSION = array();
|
||||
@@ -190,6 +212,7 @@ class ZMSessionHandler implements SessionHandlerInterface {
|
||||
return '';
|
||||
}
|
||||
public function write($id, $data) : bool {
|
||||
if (!zm_session_is_persistable()) return true;
|
||||
if (!($db = zmDbConnOrNull())) return false;
|
||||
// Create time stamp
|
||||
$access = time();
|
||||
|
||||
@@ -263,6 +263,7 @@ if ( ZM_OPT_USE_AUTH and (!isset($user) or !($user instanceof ZM\User)) and ($vi
|
||||
$postLoginQuery = $_SERVER['QUERY_STRING'];
|
||||
$redirect = '?view=login'.($postLoginQuery?'&postLoginQuery=' . urlencode($postLoginQuery):'');
|
||||
zm_session_start();
|
||||
zm_session_persist(); // must survive the redirect even if the client had no cookie
|
||||
$_SESSION['postLoginQuery'] = $postLoginQuery;
|
||||
session_write_close();
|
||||
ZM\Debug("Redirecting to $redirect");
|
||||
|
||||
Reference in new issue
Block a user