$savePath, 'sessionName' => $sessionName]); return true; } function sess_close() { global $db_link; log_session_debug($db_link, "Session closed"); return true; } function sess_read($sessionId) { global $db_link; log_session_debug($db_link, "Reading session", ['sessionId' => $sessionId]); $stmt = $db_link->prepare("SELECT data FROM " . SESSION_TABLE . " WHERE id = ?"); $stmt->execute([$sessionId]); $row = $stmt->fetch(PDO::FETCH_ASSOC); $data = $row ? $row['data'] : ''; log_session_debug($db_link, "Session data retrieved", ['length' => strlen($data), 'exists' => !empty($data)]); return $data; } function sess_write($sessionId, $data) { global $db_link; log_session_debug($db_link, "Writing session", ['sessionId' => $sessionId, 'data_length' => strlen($data)]); $time = time(); $stmt = $db_link->prepare("INSERT INTO " . SESSION_TABLE . " (id, data, last_accessed) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE data = ?, last_accessed = ?"); $success = $stmt->execute([$sessionId, $data, $time, $data, $time]); if (!$success) { $error = $stmt->errorInfo(); LOG_DEBUG($db_link, "Session write failed: " . print_r($error, true)); log_session_debug($db_link, "Session write query failed", $error); return false; } log_session_debug($db_link, "Session write successful"); return true; } function sess_destroy($sessionId) { global $db_link; log_session_debug($db_link, "Destroying session", ['sessionId' => $sessionId]); $stmt = $db_link->prepare("DELETE FROM " . SESSION_TABLE . " WHERE id = ?"); $success = $stmt->execute([$sessionId]); if (!$success) { $error = $stmt->errorInfo(); LOG_DEBUG($db_link, "Session destroy failed: " . print_r($error, true)); log_session_debug($db_link, "Session destroy query failed", $error); return false; } log_session_debug($db_link, "Session destroy successful"); return true; } function sess_gc($maxLifetime) { global $db_link; log_session_debug($db_link, "Running session GC", ['maxLifetime' => $maxLifetime]); $old = time() - $maxLifetime; $stmt = $db_link->prepare("DELETE FROM " . SESSION_TABLE . " WHERE last_accessed < ?"); $success = $stmt->execute([$old]); if (!$success) { $error = $stmt->errorInfo(); LOG_DEBUG($db_link, "Session GC failed: " . print_r($error, true)); log_session_debug($db_link, "Session GC query failed", $error); return false; } log_session_debug($db_link, "Session GC completed"); return true; } function login($db) { log_session_debug($db, "Login function started", [ 'session_status' => session_status(), 'session_id' => session_id(), 'has_post' => !empty($_POST), 'post_login' => !empty($_POST['login']), 'current_cookies' => $_COOKIE ]); $redirect_url = getSafeRedirectUrl(DEFAULT_PAGE); if ($redirect_url == DEFAULT_PAGE) { $current_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $current_path = $current_path ? rtrim($current_path, '/') : '/'; $login_path = rtrim(LOGIN_PAGE, '/'); $logout_path = rtrim(LOGOUT_PAGE, '/'); if ($current_path !== $login_path && $current_path !== $logout_path) { $redirect_url = safeUrlEncode($_SERVER['REQUEST_URI']); } } log_session_debug($db, "Redirect URL determined", ['redirect_url' => $redirect_url]); if (!empty($_SESSION['user_id'])) { log_session_debug($db, "Found user_id in session, validating", ['user_id' => $_SESSION['user_id']]); if (validate_session($db)) { log_session_debug($db, "Session validation successful"); return true; } else { log_session_debug($db, "Session validation failed, continuing to other auth methods"); } } else { log_session_debug($db, "No user_id found in session"); } if (strpos($_SERVER['REQUEST_URI'], '/api.php') === 0) { log_session_debug($db, "API request detected, attempting silent auth"); return IsSilentAuthenticated($db); } if (!empty($_POST['login']) && !empty($_POST['password'])) { log_session_debug($db, "POST login attempt", ['login' => $_POST['login']]); if (authenticate_by_credentials($db, $_POST['login'], $_POST['password'])) { LOG_INFO($db, "Logged in customer id: ".$_SESSION['user_id']." name: ".$_SESSION['login']." from ".$_SESSION['ip']." with acl: ".$_SESSION['acl']." url: ".$redirect_url); log_session_debug($db, "Login successful via credentials"); session_write_close(); session_start(); return true; } log_session_debug($db, "Login failed via credentials"); sleep(1); } else { log_session_debug($db, "No POST credentials provided"); } log_session_debug($db, "All auth methods failed, calling logout"); logout($db, FALSE, $redirect_url); exit; } function authenticate_by_credentials($db, $login, $password) { log_session_debug($db, "Authenticating by credentials", ['login' => $login]); $login = trim($login); $stmt = $db->prepare("SELECT * FROM `Customers` WHERE Login = ?"); $stmt->execute([$login]); $user = $stmt->fetch(PDO::FETCH_ASSOC); if (empty($user)) { log_session_debug($db, "User not found in database"); sleep(1); return false; } log_session_debug($db, "User found", ['user_id' => $user['id']]); if (!password_verify($password, $user['password'])) { log_session_debug($db, "Password verification failed"); sleep(1); return false; } log_session_debug($db, "Password verified, creating session"); $regenerate_result = session_regenerate_id(true); log_session_debug($db, "Session regenerate result", ['success' => $regenerate_result, 'new_sid' => session_id()]); $_SESSION = [ 'user_id' => $user['id'], 'login' => $user['Login'], 'acl' => $user['rights'], 'ip' => get_client_ip(), 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'created' => time() ]; log_session_debug($db, "Session data populated", $_SESSION); $sessionId = session_id(); $ip = $_SESSION['ip']; $userAgent = $_SESSION['user_agent']; $time = time(); $stmt = $db->prepare("INSERT INTO " . USER_SESSIONS_TABLE . " (session_id, user_id, ip_address, user_agent, created_at, last_activity) VALUES (?, ?, ?, ?, ?, ?)"); $success = $stmt->execute([$sessionId, $user['id'], $ip, $userAgent, $time, $time]); if (!$success) { $error = $stmt->errorInfo(); LOG_DEBUG($db, "Session DB error: " . print_r($error, true)); log_session_debug($db, "User session insert failed", $error); return false; } log_session_debug($db, "User session record created successfully"); return true; } function validate_session($db) { log_session_debug($db, "Validating session", [ 'session_data' => $_SESSION, 'current_ip' => get_client_ip(), 'current_ua' => ($_SERVER['HTTP_USER_AGENT'] ?? '') ]); if ($_SESSION['ip'] !== get_client_ip() || $_SESSION['user_agent'] !== ($_SERVER['HTTP_USER_AGENT'] ?? '')) { log_session_debug($db, "Session validation failed - IP or User-Agent mismatch", [ 'session_ip' => $_SESSION['ip'], 'current_ip' => get_client_ip(), 'session_ua' => $_SESSION['user_agent'], 'current_ua' => ($_SERVER['HTTP_USER_AGENT'] ?? '') ]); logout($db); return false; } $sessionId = session_id(); $stmt = $db->prepare("SELECT 1 FROM " . USER_SESSIONS_TABLE . " WHERE session_id = ? AND user_id = ? AND is_active = 1 LIMIT 1"); $stmt->execute([$sessionId, $_SESSION['user_id']]); if ($stmt->rowCount() === 0) { log_session_debug($db, "Session validation failed - no active session in database"); logout($db); return false; } $stmt = $db->prepare("UPDATE " . USER_SESSIONS_TABLE . " SET last_activity = ? WHERE session_id = ?"); $stmt->execute([time(), $sessionId]); log_session_debug($db, "Session validation successful"); return true; } function get_client_ip() { $ip = '127.0.0.1'; foreach (['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'] as $key) { if (!empty($_SERVER[$key])) { $ip = trim(current(explode(',', $_SERVER[$key]))); if (filter_var($ip, FILTER_VALIDATE_IP)) { break; } } } log_session_debug($GLOBALS['db_link'], "Client IP determined", ['ip' => $ip]); return $ip; } function IsSilentAuthenticated($db) { log_session_debug($db, "Silent authentication attempt"); if (!empty($_SESSION['user_id'])) { log_session_debug($db, "Silent auth - already has user_id in session"); return true; } $auth_ip = get_client_ip(); $api_key = ''; $login = ''; if (!empty($_GET['api_key'])) { $api_key = trim($_GET['api_key']); } elseif (!empty($_POST['api_key'])) { $api_key = trim($_POST['api_key']); } if (!empty($_GET['login'])) { $login = trim($_GET['login']); } elseif (!empty($_POST['login'])) { $login = trim($_POST['login']); } log_session_debug($db, "Silent auth parameters", ['login' => $login, 'has_api_key' => !empty($api_key)]); if (empty($login) || empty($api_key) || strlen($api_key) < 20) { log_session_debug($db, "Silent auth failed - missing parameters"); return false; } $stmt = $db->prepare("SELECT id, rights FROM Customers WHERE Login = ? AND api_key = ? LIMIT 1"); $stmt->execute([$login, $api_key]); if ($stmt->rowCount() === 0) { LOG_DEBUG($db, "API auth failed for: $login"); log_session_debug($db, "Silent auth failed - user not found or invalid API key"); return false; } $user = $stmt->fetch(PDO::FETCH_ASSOC); $_SESSION = [ 'user_id' => $user['id'], 'login' => $login, 'acl' => $user['rights'], 'ip' => $auth_ip, 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'api_auth' => true ]; log_session_debug($db, "Silent auth successful", ['user_id' => $user['id'], 'login' => $login]); LOG_INFO($db, "Logged in to api customer id: ".$_SESSION['user_id']." name: ".$_SESSION['login']." from ".$_SESSION['ip']." with acl: ".$_SESSION['acl']); return true; } function logout($db, $silent = FALSE, $redirect_url = DEFAULT_PAGE) { log_session_debug($db, "Logout function called", [ 'silent' => $silent, 'redirect_url' => $redirect_url, 'session_status' => session_status(), 'session_id' => session_id() ]); if (session_status() === PHP_SESSION_ACTIVE) { $user_info = isset($_SESSION['user_id']) ? "customer id: ".$_SESSION['user_id']." name: ".$_SESSION['login']." from ".$_SESSION['ip']." with acl: ".$_SESSION['acl'] : "no user session data"; LOG_INFO($db, "Logout " . $user_info); $sessionId = session_id(); if ($sessionId) { $stmt = $db->prepare("UPDATE " . USER_SESSIONS_TABLE . " SET is_active = 0 WHERE session_id = ?"); $result = $stmt->execute([$sessionId]); log_session_debug($db, "Session deactivation query executed", ['success' => (bool)$result]); } $_SESSION = []; session_destroy(); if (!headers_sent()) { setcookie(session_name(), '', time() - SESSION_LIFETIME, '/'); if (isset($_COOKIE['Auth'])) { setcookie('Auth', '', time() - SESSION_LIFETIME, '/'); } log_session_debug($db, "Session cookies cleared"); } } else { log_session_debug($db, "Logout - no active session to destroy"); } if (!$silent && !headers_sent()) { log_session_debug($db, "Performing redirect after logout"); if ($redirect_url == DEFAULT_PAGE || empty($redirect_url) || $redirect_url == '/') { header('Location: ' . LOGIN_PAGE); } else { header('Location: ' . LOGIN_PAGE . '?redirect_url=' . urlencode($redirect_url)); } } } // Инициализация системы сессий log_session_debug($db_link, "Before init_db_sessions"); init_db_sessions($db_link); // Инициализация сессии log_session_debug($db_link, "Before session_start check"); if (session_status() !== PHP_SESSION_ACTIVE) { log_session_debug($db_link, "Starting session"); session_start(); log_session_debug($db_link, "After session_start", [ 'session_status' => session_status(), 'session_id' => session_id(), 'session_cookie_params' => session_get_cookie_params() ]); } else { log_session_debug($db_link, "Session already active", [ 'session_id' => session_id(), 'session_status' => session_status() ]); } log_session_debug($db_link, "=== SESSION DEBUG END ===");