Авторизация и аутентификация в PHP: от основ до защиты
Безопасность веб-приложений начинается с правильной реализации аутентификации (проверки подлинности пользователя) и авторизации (проверки его прав доступа). В PHP эти механизмы можно реализовать как с помощью встроенных функций, так и используя специализированные библиотеки. В этой статье мы разберем ключевые концепции, напишем примеры кода и рассмотрим лучшие практики защиты.
1. Основные понятия: аутентификация vs авторизация
Прежде чем писать код, важно четко разграничить два термина:
- Аутентификация — процесс проверки, что пользователь является тем, за кого себя выдает (обычно через логин и пароль).
- Авторизация — процесс определения, какие ресурсы или действия доступны аутентифицированному пользователю (например, роль "admin" или "user").
Ошибки в реализации любого из этих этапов могут привести к утечке данных или несанкционированному доступу.
2. Базовая аутентификация через сессии (нативный PHP)
Самый распространенный способ — использование сессий. PHP предоставляет встроенный механизм $_SESSION. Рассмотрим простой пример.
Шаг 1: Форма входа (login.php)
<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<title>Вход на сайт</title>
</head>
<body>
<form method="POST" action="login.php">
<label>Логин:</label>
<input type="text" name="username" required>
<label>Пароль:</label>
<input type="password" name="password" required>
<button type="submit" name="login">Войти</button>
</form>
</body>
</html>
Шаг 2: Обработка входа (тот же login.php)
<?php
session_start();
require_once 'db.php'; // подключение к БД
if (isset($_POST['login'])) {
$username = trim($_POST['username']);
$password = $_POST['password'];
// 1. Подготовленный запрос для защиты от SQL-инъекций
$stmt = $pdo->prepare("SELECT id, password_hash FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
// 2. Проверка пароля через password_verify
if ($user && password_verify($password, $user['password_hash'])) {
// Аутентификация успешна
$_SESSION['user_id'] = $user['id'];
$_SESSION['logged_in'] = true;
header("Location: dashboard.php");
exit;
} else {
$error = "Неверный логин или пароль";
}
}
?>
Шаг 3: Проверка авторизации на защищенной странице
<?php
session_start();
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
header("Location: login.php");
exit;
}
// Доступ разрешен
echo "Добро пожаловать, пользователь #" . htmlspecialchars($_SESSION['user_id']);
?>
3. Хеширование паролей: никогда не храните пароли в открытом виде
PHP предоставляет безопасные функции для работы с паролями:
password_hash($password, PASSWORD_BCRYPT)— создает хеш с солью автоматически.password_verify($password, $hash)— проверяет пароль против хеша.
Пример регистрации пользователя:
<?php
$password = "user123";
$hash = password_hash($password, PASSWORD_BCRYPT);
// Сохраняем $hash в базу данных
$stmt = $pdo->prepare("INSERT INTO users (username, password_hash) VALUES (?, ?)");
$stmt->execute([$username, $hash]);
?>
Важно: никогда не используйте md5() или sha1() для паролей — они устарели и легко взламываются.
4. Ролевая авторизация (Role-Based Access Control)
Для разграничения прав используйте роли. Добавьте поле role в таблицу пользователей (например, 'admin', 'editor', 'user').
Пример проверки прав доступа:
<?php
session_start();
// Предположим, что роль хранится в сессии при логине
$role = $_SESSION['role'] ?? 'guest';
function isAdmin(): bool {
return isset($_SESSION['role']) && $_SESSION['role'] === 'admin';
}
if (!is