Аутентификация пользователей: создание формы входа и регистрации

Раздел: Веб-разработка -> Аутентификация

Основы регистрации пользователей на PHP и MySQL

Наиболее безопасный и современный способ регистрации пользователей включает использование PDO (PHP Data Objects) для работы с базой данных и функции password_hash для хеширования паролей. Такой подход предотвращает SQL-инъекции и обеспечивает надёжное хранение учётных данных.

Пример реализации:

// Подключение к БД через PDO
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$user = 'root';
$pass = '';
$options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];
$pdo = new PDO($dsn, $user, $pass, $options);

// Получение данных из формы
$login = $_POST['login'] ?? '';
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';

// Валидация
if (empty($login) || empty($email) || empty($password)) {
    die('Заполните все поля');
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    die('Некорректный email');
}

// Проверка уникальности
$stmt = $pdo->prepare('SELECT id FROM users WHERE login = :login OR email = :email');
$stmt->execute(['login' => $login, 'email' => $email]);
if ($stmt->fetch()) {
    die('Пользователь с таким логином или email уже существует');
}

// Хеширование пароля
$passwordHash = password_hash($password, PASSWORD_DEFAULT);

// Вставка в БД
$stmt = $pdo->prepare('INSERT INTO users (login, email, password_hash, reg_date) VALUES (:login, :email, :password_hash, NOW())');
$stmt->execute([
    'login' => $login,
    'email' => $email,
    'password_hash' => $passwordHash
]);

echo 'Регистрация прошла успешно';

Admin index php login php (страница входа администратора php)

Создание таблицы users в MySQL:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    login VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    reg_date DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Php code login (код страницы входа php)

Типичные проблемы и их решения:

  • SQL-инъекция – решается использованием подготовленных запросов (prepare/execute).
  • Небезопасное хранение паролей – вместо md5 или sha1 следует применять password_hash с автоматической солью.
  • Повторная отправка формы – помогает механизм CSRF-токенов или проверка уникальности запроса.
  • Некорректная кодировка – установка charset=utf8 при подключении и в таблице.

Каким образом можно реализовать регистрацию с использованием mysqli вместо PDO?

При использовании расширения mysqli также применяются подготовленные запросы, но синтаксис отличается:

$mysqli = new mysqli('localhost', 'root', '', 'test');
$mysqli->set_charset('utf8');

$stmt = $mysqli->prepare('INSERT INTO users (login, email, password_hash) VALUES (?, ?, ?)');
$stmt->bind_param('sss', $login, $email, $passwordHash);
$stmt->execute();

Request login php (запрос на вход php)

Этот вариант удобен для проектов, уже использующих mysqli, но PDO даёт большую гибкость при смене СУБД.

Как добавить регистрацию с подтверждением email?

После вставки записи генерируется уникальный токен, который отправляется на почту. Пользователь активирует аккаунт, переходя по ссылке.

$token = bin2hex(random_bytes(32));
$stmt = $pdo->prepare('INSERT INTO users (...) VALUES (?, ?, ?, ?, 0)'); // active = 0
// Сохранение token в отдельной таблице или поле email_token
// Отправка письма с ссылкой: http://example.com/activate.php?token=$token

Localhost register php (регистрация на локальном сервере)

В файле activate.php токен проверяется, и поле active устанавливается в 1.

Как защитить форму регистрации от автоматических регистраций с помощью капчи?

Интеграция с Google reCAPTCHA v3 или v2. В форму добавляется скрытое поле, на сервере проверяется ответ.

// На стороне клиента
<script src="https://www.google.com/recaptcha/api.js"></script>
<div class="g-recaptcha" data-sitekey="your_site_key"></div>

// На стороне сервера
$recaptchaResponse = $_POST['g-recaptcha-response'];
$secretKey = 'your_secret_key';
$verify = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secretKey&response=$recaptchaResponse");
$captchaSuccess = json_decode($verify);
if (!$captchaSuccess->success) {
    die('Ошибка проверки капчи');
}

регистрации php mysql (регистрация пользователей на php и mysql)

Каким образом можно выполнять асинхронную проверку логина или email без перезагрузки страницы?

Используется AJAX-запрос к PHP-скрипту, который проверяет уникальность и возвращает JSON.

// JavaScript (fetch)
let login = document.getElementById('login').value;
fetch('check_login.php?login=' + encodeURIComponent(login))
    .then(response => response.json())
    .then(data => {
        if (data.exists) {
            // показать ошибку
        }
    });

// check_login.php
$login = $_GET['login'];
$stmt = $pdo->prepare('SELECT id FROM users WHERE login = ?');
$stmt->execute([$login]);
echo json_encode(['exists' => (bool)$stmt->fetch()]);

Как можно реализовать регистрацию через сторонние сервисы (OAuth)?

Для входа через Google, VK или Facebook требуется библиотека (например, HybridAuth) или прямая работа с API. Пользователь перенаправляется на страницу провайдера, после авторизации данные возвращаются и создаётся или связывается локальная учётная запись.

Этот вариант упрощает пользовательский опыт, но требует регистрации приложения у провайдера.

Стоит ли использовать устаревшие методы хеширования (md5, sha1) с солью?

Не рекомендуется. Такие хеши легко поддаются атаке по радужным таблицам, даже с солью. Современная функция password_hash использует алгоритм bcrypt или argon2, который специально замедлен и включает автоматическую соль.

Частая ошибка при использовании password_hash: неверная длина поля в таблице. Хеш может быть до 255 символов, поэтому поле должно быть VARCHAR(255) или больше.

- Index php id login (авторизация через параметр id в index.php)
- Login php username (обработка имени пользователя при входе php)
- Login php page (страница входа php)

Расширенные примеры регистрации

Ниже приведены более сложные сценарии с полным кодом и пояснениями.

Пример 1. Регистрация с транзакцией и логированием

Пример
try {
    $pdo->beginTransaction();
    
    $stmt = $pdo->prepare('INSERT INTO users (login, email, password_hash) VALUES (?, ?, ?)');
    $stmt->execute([$login, $email, $hash]);
    $userId = $pdo->lastInsertId();
    
    // Логируем событие
    $logStmt = $pdo->prepare('INSERT INTO logs (user_id, action, time) VALUES (?, ?, NOW())');
    $logStmt->execute([$userId, 'registration']);
    
    $pdo->commit();
    echo 'Регистрация выполнена, ID: ' . $userId;
} catch (Exception $e) {
    $pdo->rollBack();
    error_log($e->getMessage());
    die('Ошибка при регистрации');
}

Результат: при успешной регистрации создаётся запись в таблице users и запись в logs. При ошибке обе операции отменяются.

Пример 2. Асинхронная проверка логина с защитой от XSS

Клиентская часть (fetch):

Пример
const loginInput = document.querySelector('#login');
const feedback = document.querySelector('#login-feedback');

loginInput.addEventListener('blur', function() {
    fetch('check_login.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: 'login=' + encodeURIComponent(this.value)
    })
    .then(r => r.json())
    .then(data => {
        feedback.textContent = data.exists ? 'Логин занят' : 'Логин свободен';
        feedback.className = data.exists ? 'error' : 'success';
    });
});

Сервер (check_login.php):

Пример
$login = $_POST['login'] ?? '';
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $login)) {
    echo json_encode(['exists' => false, 'error' => 'Некорректный логин']);
    exit;
}
$stmt = $pdo->prepare('SELECT 1 FROM users WHERE login = ?');
$stmt->execute([$login]);
echo json_encode(['exists' => (bool)$stmt->fetchColumn()]);

Результат: при вводе логина на сервер отправляется AJAX-запрос, возвращается JSON с boolean и отображается подсказка.

Пример 3. Регистрация с подтверждением email и токеном

Пример
// Генерация токена
$token = bin2hex(random_bytes(32));
$hash = password_hash($password, PASSWORD_DEFAULT);

try {
    $pdo->beginTransaction();
    $stmt = $pdo->prepare('INSERT INTO users (login, email, password_hash, active, email_token) VALUES (?, ?, ?, 0, ?)');
    $stmt->execute([$login, $email, $hash, $token]);
    $pdo->commit();
    
    // Отправка письма (упрощённо)
    $link = "http://example.com/activate.php?token=$token";
    mail($email, 'Подтверждение регистрации', "Для активации перейдите: $link");
    echo 'Проверьте почту для активации аккаунта';
} catch (Exception $e) {
    $pdo->rollBack();
    die('Ошибка');
}

// activate.php
$token = $_GET['token'] ?? '';
$stmt = $pdo->prepare('UPDATE users SET active = 1 WHERE email_token = ? AND active = 0');
$stmt->execute([$token]);
if ($stmt->rowCount()) {
    echo 'Аккаунт активирован';
} else {
    echo 'Неверный или использованный токен';
}

Результат: после регистрации пользователь получает письмо со ссылкой. Переход по ней активирует учётную запись.

Пример 4. Интеграция Google reCAPTCHA v3

Пример
// Форма (HTML)
<input type="hidden" name="recaptcha_response" id="recaptchaResponse">
<script>
grecaptcha.ready(function() {
    grecaptcha.execute('site_key', {action: 'register'}).then(function(token) {
        document.getElementById('recaptchaResponse').value = token;
    });
});
</script>

// PHP обработка
$recaptcha = $_POST['recaptcha_response'];
$secret = 'secret_key';
$verify = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$recaptcha");
$response = json_decode($verify);
if ($response->score < 0.5) {
    die('Подозрительная активность');
}

Результат: Google оценивает действия пользователя по шкале от 0 до 1; если оценка низкая, регистрация отклоняется.

Пример 5. Использование password_needs_rehash для обновления хеша

Пример
if (password_verify($password, $storedHash)) {
    if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) {
        $newHash = password_hash($password, PASSWORD_DEFAULT);
        $stmt = $pdo->prepare('UPDATE users SET password_hash = ? WHERE id = ?');
        $stmt->execute([$newHash, $userId]);
    }
    // успешный вход
}

Результат: при каждой аутентификации проверяется, нужно ли обновить хеш до более современного алгоритма без вмешательства пользователя.

Регистрация пользователей на PHP и MySQL - comments

En
регистрации php mysql (php)