auth.utils.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. define("CONFIG", 1);
  3. define("SQL", 1);
  4. require_once($_SERVER['DOCUMENT_ROOT'] . "/cfg/config.php");
  5. require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/sql.php");
  6. require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/common.php");
  7. ini_set('session.use_trans_sid', true);
  8. ini_set('session.use_only_cookies', false);
  9. ini_set('session.gc_maxlifetime', 3600*24);
  10. define('SESSION_TABLE', 'sessions');
  11. define('USER_SESSIONS_TABLE', 'user_sessions');
  12. // Инициализация сессий в БД
  13. function init_db_sessions($db) {
  14. // Настройка обработчиков сессий
  15. session_set_save_handler(
  16. 'sess_open',
  17. 'sess_close',
  18. 'sess_read',
  19. 'sess_write',
  20. 'sess_destroy',
  21. 'sess_gc'
  22. );
  23. register_shutdown_function('session_write_close');
  24. }
  25. // Обработчики сессий (процедурный стиль)
  26. function sess_open($savePath, $sessionName) { return true; }
  27. function sess_close() { return true; }
  28. function sess_read($sessionId) {
  29. global $db_link;
  30. $sessionId = mysqli_real_escape_string($db_link, $sessionId);
  31. $result = mysqli_query($db_link, "SELECT data FROM ".SESSION_TABLE." WHERE id = '$sessionId'");
  32. return $result && mysqli_num_rows($result) ? mysqli_fetch_assoc($result)['data'] : '';
  33. }
  34. function sess_write($sessionId, $data) {
  35. global $db_link;
  36. $sessionId = mysqli_real_escape_string($db_link, $sessionId);
  37. $data = mysqli_real_escape_string($db_link, $data);
  38. $time = time();
  39. $query = "INSERT INTO ".SESSION_TABLE." (id, data, last_accessed)
  40. VALUES ('$sessionId', '$data', $time)
  41. ON DUPLICATE KEY UPDATE data = '$data', last_accessed = $time";
  42. return mysqli_query($db_link, $query);
  43. }
  44. function sess_destroy($sessionId) {
  45. global $db_link;
  46. $sessionId = mysqli_real_escape_string($db_link, $sessionId);
  47. return mysqli_query($db_link, "DELETE FROM ".SESSION_TABLE." WHERE id = '$sessionId'");
  48. }
  49. function sess_gc($maxLifetime) {
  50. global $db_link;
  51. $old = time() - $maxLifetime;
  52. return mysqli_query($db_link, "DELETE FROM ".SESSION_TABLE." WHERE last_accessed < $old");
  53. }
  54. // Инициализация системы сессий
  55. init_db_sessions($db_link);
  56. // Старт сессии с безопасными настройками
  57. session_start([
  58. 'cookie_lifetime' => 86400 * 30,
  59. 'cookie_secure' => true,
  60. 'cookie_httponly' => true,
  61. 'cookie_samesite' => 'Strict',
  62. 'gc_maxlifetime' => 86400 * 30
  63. ]);
  64. function login($db) {
  65. // 1. Проверка активной сессии
  66. if (!empty($_SESSION['user_id']) && validate_session($db)) {
  67. // Дополнительная валидация сессии
  68. if ($_SESSION['ip'] === get_user_ip() &&
  69. $_SESSION['user_agent'] === ($_SERVER['HTTP_USER_AGENT'] ?? '')) {
  70. return true;
  71. }
  72. // Несоответствие параметров - разрушаем сессию
  73. logout($db);
  74. }
  75. // 2. Проверка API-авторизации (для API-запросов)
  76. if (strpos($_SERVER['REQUEST_URI'], '/api.php') === 0) {
  77. return IsSilentAuthenticated($db);
  78. }
  79. // 4. Проверка логина/пароля из POST-данных (обычная форма входа)
  80. if (!empty($_POST['login']) && !empty($_POST['password'])) {
  81. if (authenticate_by_credentials($db, $_POST['login'], $_POST['password'])) {
  82. return true;
  83. }
  84. // Неудачная попытка входа
  85. sleep(1); // Защита от брутфорса
  86. }
  87. // 5. Если ни один метод не сработал - требовать авторизацию
  88. logout($db);
  89. exit;
  90. }
  91. function authenticate_by_credentials($db,$login,$password) {
  92. $login = mysqli_real_escape_string($db, trim($login));
  93. $query = "SELECT * FROM `Customers` WHERE Login='{$login}'";
  94. $user = get_record_sql($db, $query);
  95. if (!empty($user)) {
  96. if (!password_verify($password, $user['password'])) {
  97. sleep(1);
  98. return false;
  99. }
  100. } else {
  101. sleep(1);
  102. return false;
  103. }
  104. // Создание сессии
  105. session_regenerate_id(true);
  106. $_SESSION = [
  107. 'user_id' => $user['id'],
  108. 'login' => $user['Login'],
  109. 'acl' => $user['rights'],
  110. 'ip' => get_client_ip(),
  111. 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
  112. 'created' => time()
  113. ];
  114. // Запись сессии в БД
  115. $sessionId = mysqli_real_escape_string($db, session_id());
  116. $ip = mysqli_real_escape_string($db, $_SESSION['ip']);
  117. $userAgent = mysqli_real_escape_string($db, $_SESSION['user_agent']);
  118. $time = time();
  119. mysqli_query($db,
  120. "INSERT INTO ".USER_SESSIONS_TABLE."
  121. (session_id, user_id, ip_address, user_agent, created_at, last_activity)
  122. VALUES (
  123. '$sessionId',
  124. {$user['id']},
  125. '$ip',
  126. '$userAgent',
  127. $time,
  128. $time
  129. )");
  130. return true;
  131. }
  132. function validate_session($db) {
  133. // Проверка IP и User-Agent
  134. if ($_SESSION['ip'] !== get_client_ip() ||
  135. $_SESSION['user_agent'] !== ($_SERVER['HTTP_USER_AGENT'] ?? '')) {
  136. logout($db);
  137. return false;
  138. }
  139. // Проверка активности сессии в БД
  140. $sessionId = mysqli_real_escape_string($db, session_id());
  141. $result = mysqli_query($db,
  142. "SELECT 1
  143. FROM ".USER_SESSIONS_TABLE."
  144. WHERE
  145. session_id = '$sessionId' AND
  146. user_id = {$_SESSION['user_id']} AND
  147. is_active = 1
  148. LIMIT 1");
  149. if (!$result || mysqli_num_rows($result) === 0) {
  150. logout($db);
  151. return false;
  152. }
  153. // Обновление времени активности
  154. mysqli_query($db,
  155. "UPDATE ".USER_SESSIONS_TABLE."
  156. SET last_activity = ".time()."
  157. WHERE session_id = '$sessionId'");
  158. return true;
  159. }
  160. // Вспомогательная функция
  161. function get_client_ip() {
  162. return $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
  163. }
  164. // Авторизация по API-ключу (без пароля)
  165. function IsSilentAuthenticated($db) {
  166. if (!empty($_SESSION['user_id'])) {
  167. return true;
  168. }
  169. $auth_ip = get_user_ip();
  170. $api_key = '';
  171. // Получаем ключ из GET или POST
  172. if (!empty($_GET['api_key'])) {
  173. $api_key = trim($_GET['api_key']);
  174. } elseif (!empty($_POST['api_key'])) {
  175. $api_key = trim($_POST['api_key']);
  176. }
  177. if (!empty($_GET['login'])) {
  178. $login = trim($_GET['login']);
  179. } elseif (!empty($_POST['login'])) {
  180. $login = trim($_POST['login']);
  181. }
  182. if (empty($login) || empty($api_key) || strlen($api_key) < 20) {
  183. return false;
  184. }
  185. // Экранирование и подготовка
  186. $login = mysqli_real_escape_string($db, $login);
  187. $api_key = mysqli_real_escape_string($db, $api_key);
  188. // Ищем пользователя с таким логином и API-ключом
  189. $query = "SELECT id, rights FROM Customers
  190. WHERE Login = '$login' AND api_key = '$api_key'
  191. LIMIT 1";
  192. $result = mysqli_query($db, $query);
  193. if (!$result || mysqli_num_rows($result) === 0) {
  194. error_log("API auth failed for: $login");
  195. return false;
  196. }
  197. $user = mysqli_fetch_assoc($result);
  198. // Создаем сессию
  199. $_SESSION = [
  200. 'user_id' => $user['id'],
  201. 'login' => $login,
  202. 'acl' => $user['rights'],
  203. 'ip' => $auth_ip,
  204. 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
  205. 'api_auth' => true // Метка API-аутентификации
  206. ];
  207. return true;
  208. }
  209. // Выход из системы (полная версия)
  210. function logout($db, $silent = FALSE) {
  211. if (session_status() === PHP_SESSION_ACTIVE) {
  212. // Деактивация сессии в БД
  213. $sessionId = mysqli_real_escape_string($db, session_id());
  214. mysqli_query($db,
  215. "UPDATE ".USER_SESSIONS_TABLE."
  216. SET is_active = 0
  217. WHERE session_id = '$sessionId'");
  218. // Очистка данных
  219. $_SESSION = [];
  220. session_destroy();
  221. setcookie(session_name(), '', time() - 3600, '/');
  222. // Удаление авторизационной куки (если есть)
  223. if (isset($_COOKIE['Auth'])) {
  224. setcookie('Auth', '', time() - 3600, '/');
  225. }
  226. }
  227. if (!$silent) {
  228. header('Location: /login.php');
  229. //?redirect=' . urlencode($_SERVER['REQUEST_URI']));
  230. }
  231. }