Исходный код страницы входа на PHP: от основ до продвинутых техник
Реализация страницы входа на PHP: подходы и примеры
Основной рекомендуемый способ: аутентификация через базу данных с использованием подготовленных запросов и хеширования паролей
Этот подход обеспечивает безопасность, защиту от SQL-инъекций и корректное хранение учётных данных. Сессии позволяют сохранять состояние авторизации.
Как организовать процесс входа с проверкой в MySQL и стартом сессии?
<?php
session_start();
require 'db.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
if (empty($email) || empty($password)) {
$_SESSION['error'] = 'Заполните все поля.';
header('Location: login.php');
exit;
}
$stmt = $pdo->prepare('SELECT id, email, password FROM users WHERE email = :email');
$stmt->execute(['email' => $email]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
$_SESSION['email'] = $user['email'];
header('Location: dashboard.php');
} else {
$_SESSION['error'] = 'Неверный email или пароль.';
header('Location: login.php');
}
exit;
}
?>
Admin index php login php (страница входа администратора php)
Пояснение: сессия запускается в самом начале. Данные из формы получаются через POST. Подготовленный запрос защищает от инъекций. Пароль проверяется функцией password_verify – пароль должен быть сохранён хешем (например, при регистрации через password_hash). После успешной проверки идентификатор сессии обновляется и сохраняется ID пользователя.
Типичные ошибки:
- Забыли вызвать
session_start()– сессионные переменные не будут доступны. - Использование
md5илиsha1для хранения паролей – они ненадёжны. Следует применять толькоpassword_hashиpassword_verify. - Отсутствие проверки на пустые поля – возможна обработка некорректных данных.
- Передача пароля через GET – пароль будет виден в URL и логах сервера. Используется только POST.
Решение: всегда использовать prepare, проверять метод запроса, очищать вывод ошибок на продакшене, применять session_regenerate_id после входа.
Как сделать простейшую страницу входа без базы данных, с жёстко заданными логином и паролем?
Этот вариант подходит для временных прототипов или очень маленьких проектов, где нет необходимости в масштабировании.
<?php
session_start();
$valid_username = 'admin';
$valid_password_hash = password_hash('secret', PASSWORD_DEFAULT);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if ($username === $valid_username && password_verify($password, $valid_password_hash)) {
$_SESSION['user'] = $username;
header('Location: admin.php');
} else {
$error = 'Неверные учётные данные.';
}
}
?>
Php code login (код страницы входа php)
Проблемы и их решение:
Жёстко прописанные логин и пароль неудобны при смене данных. Кроме того, пароль в исходном коде может быть скомпрометирован. Решение: вынести учётные данные в конфигурационный файл, но всё равно такой подход не рекомендуется для реальных проектов. Лучше использовать базу данных.
Как добавить защиту от CSRF на форме входа?
CSRF-токен предотвращает подделку межсайтовых запросов. Генерация токена и его проверка при отправке формы.
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
die('Ошибка CSRF-токена');
}
// остальная логика входа
}
?>
<form method="post">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<!-- остальные поля -->
</form>
Request login php (запрос на вход php)
Возможные ошибки:
Если токен не сравнивается через hash_equals, возможно уязвимость timing attack. Используйте именно эту функцию. Также важно регенерировать токен после входа для предотвращения фиксации сессии.
Как интегрировать CAPTCHA (reCAPTCHA v2) в форму входа для защиты от ботов?
Добавление reCAPTCHA снижает риск автоматических атак подбора паролей.
<?php
// server-side verification
$recaptcha_secret = 'ваш_секретный_ключ';
$recaptcha_response = $_POST['g-recaptcha-response'] ?? '';
$verify_url = 'https://www.google.com/recaptcha/api/siteverify';
$data = ['secret' => $recaptcha_secret, 'response' => $recaptcha_response];
$options = ['http' => ['method' => 'POST', 'content' => http_build_query($data)]];
$context = stream_context_create($options);
$result = file_get_contents($verify_url, false, $context);
$response = json_decode($result);
if (!$response->success) {
$error = 'Пожалуйста, пройдите проверку reCAPTCHA.';
}
?>
Проблемы:
Если ключ неверный или на сервере не включено расширение allow_url_fopen, запрос не выполнится. Альтернатива – использовать cURL. Также reCAPTCHA может не срабатывать при использовании локального сервера без SSL в старых версиях.
Расширенные примеры реализации страницы входа
Пример 1. Полный скрипт входа с PDO, подготовленными запросами и обработкой ошибок
<?php
session_start();
require_once 'config/database.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('HTTP/1.1 405 Method Not Allowed');
exit;
}
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$password = $_POST['password'] ?? '';
if (!$email || empty($password)) {
$_SESSION['error'] = 'Введите корректный email и пароль.';
header('Location: login.php');
exit;
}
try {
$stmt = $pdo->prepare('SELECT id, email, password, role FROM users WHERE email = :email LIMIT 1');
$stmt->execute(['email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
session_regenerate_id(true);
$_SESSION['user'] = [
'id' => $user['id'],
'email' => $user['email'],
'role' => $user['role'],
'ip' => $_SERVER['REMOTE_ADDR'],
'logged_at' => time()
];
// запись лога входа
$logStmt = $pdo->prepare('INSERT INTO login_log (user_id, ip, user_agent) VALUES (:uid, :ip, :ua)');
$logStmt->execute(['uid' => $user['id'], 'ip' => $_SERVER['REMOTE_ADDR'], 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
header('Location: dashboard.php');
exit;
} else {
$_SESSION['error'] = 'Неверный email или пароль.';
header('Location: login.php');
exit;
}
} catch (PDOException $e) {
// логгируем ошибку, пользователю показываем общее сообщение
error_log($e->getMessage());
$_SESSION['error'] = 'Временно недоступно. Повторите попытку позже.';
header('Location: login.php');
exit;
}
?>
Результат: при успешном входе пользователь перенаправляется на dashboard.php, при ошибке возвращается обратно с сообщением в сессии. Важно: логирование входа полезно для аудита.
Пример 2. Форма входа с отображением ошибок и сохранением введённого email
<!DOCTYPE html>
<html lang="ru">
<head><meta charset="UTF-8"><title>Вход</title></head>
<body>
<?php session_start(); ?>
<form method="post" action="login.php">
<?php if (isset($_SESSION['error'])): ?>
<p class="error"><?= htmlspecialchars($_SESSION['error'], ENT_QUOTES, 'UTF-8') ?></p>
<?php unset($_SESSION['error']); ?>
<?php endif; ?>
<label>Email: <input type="email" name="email" value="<?= htmlspecialchars($_SESSION['old_email'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required></label><br>
<label>Пароль: <input type="password" name="password" required></label><br>
<input type="submit" value="Войти">
</form>
</body>
</html>
Вывод: форма с предзаполненным email и сообщением об ошибке, если сессия содержит соответствующие данные. После отображения ошибка и старый email удаляются из сессии.
Пример 3. Вход через API с возвратом JSON и использованием токенов (без сессий)
<?php
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
if (!$data || empty($data['email']) || empty($data['password'])) {
http_response_code(400);
echo json_encode(['error' => 'Email and password required']);
exit;
}
// проверка пользователя в БД, password_verify...
// если успешно, генерируем JWT или простой токен
$token = bin2hex(random_bytes(32));
// сохраняем токен в БД для пользователя
$stmt = $pdo->prepare('INSERT INTO api_tokens (user_id, token, expires_at) VALUES (:uid, :token, :expires)');
$stmt->execute(['uid' => $user['id'], 'token' => $token, 'expires' => date('Y-m-d H:i:s', time() + 3600)]);
http_response_code(200);
echo json_encode(['token' => $token, 'expires_in' => 3600]);
Результат: клиент получает токен, который использует для последующих запросов. Этот подход подходит для SPA и мобильных приложений.