Организация аутентификации PHP на локальном сервере
Методы создания локального логина в PHP
Основное решение: сессии + база данных MySQL
Этот подход обеспечивает надёжное хранение учётных записей и гибкое управление доступом. Для локального сервера (XAMPP, OpenServer) достаточно стандартных средств PHP и MySQL.
Как реализовать защищённый вход на localhost с использованием сессий и MySQL?
Последовательность шагов:
- Создать базу данных и таблицу users (id, login, password_hash, created_at).
- Настроить подключение через PDO (prepared statements).
- Создать форму регистрации и скрипт обработки с хешированием пароля (password_hash).
- Создать форму входа, проверять пароль через password_verify, устанавливать сессионную переменную.
- На защищённых страницах проверять наличие сессии.
<?php
// config.php
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASS', '');
try {
$pdo = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die('Ошибка подключения к БД');
}
?>
Http localhost login php (локальный логин php)
<?php
// register.php
session_start();
require 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$login = trim($_POST['login']);
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare('INSERT INTO users (login, password_hash) VALUES (?, ?)');
if ($stmt->execute([$login, $hash])) {
$_SESSION['message'] = 'Регистрация успешна';
header('Location: login.php');
exit;
} else {
$error = 'Ошибка регистрации';
}
}
?>
<?php
// login.php
session_start();
require 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$login = trim($_POST['login']);
$password = $_POST['password'];
$stmt = $pdo->prepare('SELECT * FROM users WHERE login = ?');
$stmt->execute([$login]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password_hash'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['login'] = $user['login'];
header('Location: dashboard.php');
exit;
} else {
$error = 'Неверный логин или пароль';
}
}
?>
Типичные ошибки:
- Использование устаревшего хеша md5 или sha1 (решение: password_hash).
- Отсутствие prepared statements (риск SQL-инъекций).
- Неправильная настройка путей сессий (сессии не сохраняются).
- Игнорирование фильтрации ввода (trim, strip_tags).
Как защитить страницу без базы данных с помощью HTTP Basic Auth?
Подходит для быстрого ограничения доступа к папке. Сервер отправляет заголовок 401, браузер показывает диалог ввода логина и пароля.
<?php
// .htaccess (Apache) или конфигурация сервера
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /path/to/.htpasswd
Require valid-user
Файл .htpasswd создаётся утилитой htpasswd или онлайн-генератором. Хранятся логин и хеш пароля.
Проблема:
Нет возможности персонализировать страницу входа; пароль передаётся в открытом виде без HTTPS (на localhost обычно не критично).
Как реализовать логин с хранением данных в файле?
Используется для очень простых проектов без MySQL. Создаётся файл users.json с массивом логинов и хешей паролей.
// users.json
[
{"login": "admin", "password_hash": "$2y$10$..."}
]
<?php
// file_login.php
$users = json_decode(file_get_contents('users.json'), true);
foreach ($users as $user) {
if ($user['login'] === $login && password_verify($password, $user['password_hash'])) {
// установка сессии
}
}
Проблемы:
Низкая производительность при множестве пользователей, проблемы с конкурентным доступом, необходимость вручную обновлять файл.
Как упростить разработку с помощью готовой библиотеки?
Библиотеки вроде PHPass или компонента Symfony Security предоставляют готовые классы для хеширования и проверки. Пример с использованием phpass (устарел, но показателен).
require 'PasswordHash.php';
$hasher = new PasswordHash(8, false);
$hash = $hasher->HashPassword($password);
$check = $hasher->CheckPassword($password, $hash);
Современная альтернатива - использование password_hash напрямую, что уже является лучшей практикой.
Расширенные примеры с пошаговым кодом и результатами.
Пример 1. Полная система регистрации и входа на PDO с защитой от CSRF
<?php
// config.php
session_start();
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// create_table.sql
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
login VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
<?php
// generate_token.php
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<?php
// register.php
require 'config.php';
require 'generate_token.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die('CSRF token error');
}
$login = filter_input(INPUT_POST, 'login', FILTER_SANITIZE_STRING);
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_BCRYPT);
$stmt = $pdo->prepare('INSERT INTO users (login, password_hash) VALUES (?, ?)');
try {
$stmt->execute([$login, $hash]);
$_SESSION['message'] = 'Успешная регистрация';
header('Location: login.php');
exit;
} catch (PDOException $e) {
if ($e->getCode() == 23000) {
$error = 'Логин уже занят';
} else {
$error = 'Ошибка базы данных';
}
}
}
?>
Результат работы (при успешной регистрации):
Перенаправление на login.php с сообщением 'Успешная регистрация'
Пример 2. Защищённая страница dashboard.php
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
?>
<h2>Добро пожаловать, <?php echo htmlspecialchars($_SESSION['login']); ?>!</h2>
Результат (если сессия активна):
Добро пожаловать, admin!
Пример 3. Использование файлового хранилища с сериализацией
// users.txt (одна строка на пользователя: login:hash)
admin:$2y$10$abcdef...
// file_check.php
$users = file('users.txt', FILE_IGNORE_NEW_LINES);
$found = false;
foreach ($users as $line) {
list($login, $hash) = explode(':', $line, 2);
if ($login === $_POST['login'] && password_verify($_POST['password'], $hash)) {
$found = true;
break;
}
}
if ($found) { /* успех */ }
Результат:
При совпадении логина и пароля устанавливается сессия.
Пример 4. Отладка сессий на localhost
<?php
session_start();
ini_set('session.save_path', '/tmp'); // явно указать путь
var_dump(session_save_path());
?>
Возможная проблема:
Сессии не сохраняются из-за отсутствия прав на запись в папку сессий. Решение: проверить права, указать свой путь через session_save_path().