security update

This commit is contained in:
2026-01-19 08:57:58 +03:00
parent 55b3d5f088
commit 5c084c6aaa
8 changed files with 182 additions and 49 deletions

View File

@@ -1,5 +1,6 @@
<?php <?php
session_start(); header('Content-Type: application/json; charset=utf-8');
require_once '../config/session.php';
if (isset($_SESSION['user_id'])) { if (isset($_SESSION['user_id'])) {
echo json_encode([ echo json_encode([

View File

@@ -1,37 +1,47 @@
<?php <?php
error_reporting(E_ALL); error_reporting(E_ALL);
ini_set('display_errors', 1); ini_set('display_errors', 0);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 0);
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
require_once '../config/db.php'; require_once '../config/db.php';
require_once '../config/session.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$data = json_decode(file_get_contents('php://input'), true); http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Метод не поддерживается']);
$login = trim($data['username'] ?? ''); exit;
$password = $data['password'] ?? ''; }
// Поиск пользователя по username $data = json_decode(file_get_contents('php://input'), true);
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?"); if (!is_array($data)) {
$stmt->execute([$login]); http_response_code(400);
$user = $stmt->fetch(PDO::FETCH_ASSOC); echo json_encode(['success' => false, 'message' => 'Некорректные данные']);
exit;
if ($user && password_verify($password, $user['password_hash'])) { }
// Успешная авторизация
session_start(); $login = trim($data['username'] ?? '');
$_SESSION['user_id'] = $user['id']; $password = $data['password'] ?? '';
$_SESSION['username'] = $user['username'];
// Поиск пользователя по username
echo json_encode([ $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
'success' => true, $stmt->execute([$login]);
'message' => 'Вход выполнен успешно', $user = $stmt->fetch(PDO::FETCH_ASSOC);
'user' => [
'id' => $user['id'], if ($user && password_verify($password, $user['password_hash'])) {
'username' => $user['username'], // Успешная авторизация
] session_regenerate_id(true);
]); $_SESSION['user_id'] = $user['id'];
} else { $_SESSION['username'] = $user['username'];
echo json_encode(['success' => false, 'message' => 'Неверные учетные данные']);
} echo json_encode([
'success' => true,
'message' => 'Вход выполнен успешно',
'user' => [
'id' => $user['id'],
'username' => $user['username'],
]
]);
} else {
echo json_encode(['success' => false, 'message' => 'Неверные учетные данные']);
} }
?> ?>

View File

@@ -1,5 +1,18 @@
<?php <?php
session_start(); header('Content-Type: application/json; charset=utf-8');
require_once '../config/session.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Метод не поддерживается']);
exit;
}
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
}
session_destroy(); session_destroy();
echo json_encode(['success' => true]); echo json_encode(['success' => true]);
?> ?>

View File

@@ -1,7 +1,7 @@
<?php <?php
error_reporting(E_ALL); error_reporting(E_ALL);
ini_set('display_errors', 1); ini_set('display_errors', 0);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 0);
$host = 'localhost'; $host = 'localhost';
$dbname = 'users'; $dbname = 'users';
$username = 'root'; $username = 'root';

15
config/session.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
if (session_status() === PHP_SESSION_NONE) {
$isSecure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
ini_set('session.use_strict_mode', '1');
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => $isSecure,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
}
?>

View File

@@ -10,7 +10,7 @@
<script> <script>
// Проверка авторизации при загрузке страницы // Проверка авторизации при загрузке страницы
async function checkAuth() { async function checkAuth() {
const response = await fetch('api/check_auth.php'); const response = await fetch('api/check_auth.php', { credentials: 'same-origin' });
const result = await response.json(); const result = await response.json();
if (!result.isLoggedIn) { if (!result.isLoggedIn) {
@@ -23,9 +23,10 @@
} }
async function logout() { async function logout() {
await fetch('api/logout.php'); await fetch('api/logout.php', {
localStorage.removeItem('user'); method: 'POST',
localStorage.removeItem('isLoggedIn'); credentials: 'same-origin'
});
window.location.href = 'login.html'; window.location.href = 'login.html';
} }

View File

@@ -3,11 +3,15 @@ async function sendRequest(url, data) {
try { try {
const response = await fetch(url, { const response = await fetch(url, {
method: 'POST', method: 'POST',
credentials: 'same-origin',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify(data) body: JSON.stringify(data)
}); });
if (!response.ok) {
return { success: false, message: 'Ошибка сервера' };
}
return await response.json(); return await response.json();
} catch (error) { } catch (error) {
console.error('Ошибка:', error); console.error('Ошибка:', error);
@@ -45,10 +49,6 @@ if (document.getElementById('loginForm')) {
const result = await sendRequest('api/login.php', data); const result = await sendRequest('api/login.php', data);
if (result.success) { if (result.success) {
// Сохраняем данные пользователя в localStorage
localStorage.setItem('user', JSON.stringify(result.user));
localStorage.setItem('isLoggedIn', 'true');
alert(result.message); alert(result.message);
window.location.href = 'index.html'; window.location.href = 'index.html';
} else { } else {

View File

@@ -1,16 +1,109 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Вход</title> <title>Вход</title>
<style>
:root {
color-scheme: light;
--bg: #f5f7fb;
--card: #ffffff;
--text: #1b1f2a;
--muted: #6b7280;
--border: #e5e7eb;
--accent: #3b82f6;
--accent-dark: #2563eb;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
background: linear-gradient(135deg, #eef2ff, #f8fafc);
color: var(--text);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
}
.card {
width: 100%;
max-width: 380px;
background: var(--card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 24px;
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
}
h2 {
margin: 0 0 8px;
font-size: 24px;
}
.subtitle {
margin: 0 0 20px;
color: var(--muted);
font-size: 14px;
}
.field {
margin-bottom: 14px;
}
label {
display: block;
font-size: 13px;
color: var(--muted);
margin-bottom: 6px;
}
input {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 14px;
transition: border-color 0.2s, box-shadow 0.2s;
}
input:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
button {
width: 100%;
padding: 10px 12px;
border: none;
border-radius: 8px;
background: var(--accent);
color: #fff;
font-size: 15px;
cursor: pointer;
transition: background 0.2s;
}
button:hover { background: var(--accent-dark); }
.helper {
margin-top: 14px;
font-size: 12px;
color: var(--muted);
text-align: center;
}
</style>
</head> </head>
<body> <body>
<h2>Вход</h2> <div class="card">
<form id="loginForm"> <h2>Вход</h2>
<input type="text" name="username" placeholder="Логин" required> <p class="subtitle">Введите логин и пароль для доступа</p>
<input type="password" name="password" placeholder="Пароль" required> <form id="loginForm">
<button type="submit">Войти</button> <div class="field">
</form> <label for="username">Логин</label>
<input id="username" type="text" name="username" placeholder="Введите логин" required autocomplete="username" autocapitalize="off" spellcheck="false">
</div>
<div class="field">
<label for="password">Пароль</label>
<input id="password" type="password" name="password" placeholder="Введите пароль" required autocomplete="current-password">
</div>
<button type="submit">Войти</button>
</form>
<div class="helper">Доступ только для зарегистрированных пользователей</div>
</div>
<script src="js/auth.js"></script> <script src="js/auth.js"></script>
</body> </body>
</html> </html>