Система аутентификации в PHP

Активный
Статус
Сообщения
516
Лайки
32

8

месяц на сайте

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

Регистрация пользователя

Код:
<?php
function registerUser($username, $email, $password) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    // Проверка существования
    $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? OR email = ?");
    $stmt->execute([$username, $email]);
    if ($stmt->fetch()) {
        return false;
    }
    
    // Хеширование пароля
    $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
    
    // Создание пользователя
    $stmt = $pdo->prepare("INSERT INTO users (username, email, password, created_at) VALUES (?, ?, ?, NOW())");
    return $stmt->execute([$username, $email, $hashedPassword]);
}

if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['register'])) {
    $username = $_POST['username'];
    $email = $_POST['email'];
    $password = $_POST['password'];
    
    if (registerUser($username, $email, $password)) {
        echo "Регистрация успешна";
    } else {
        echo "Ошибка регистрации";
    }
}
?>

Вход в систему

Код:
<?php
session_start();

function loginUser($username, $password) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    $stmt = $pdo->prepare("SELECT id, username, password FROM users WHERE username = ?");
    $stmt->execute([$username]);
    $user = $stmt->fetch();
    
    if ($user && password_verify($password, $user['password'])) {
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['username'] = $user['username'];
        return true;
    }
    
    return false;
}

if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['login'])) {
    $username = $_POST['username'];
    $password = $_POST['password'];
    
    if (loginUser($username, $password)) {
        header('Location: dashboard.php');
        exit;
    } else {
        echo "Неверные данные";
    }
}
?>

Проверка авторизации

Код:
<?php
session_start();

function isLoggedIn() {
    return isset($_SESSION['user_id']);
}

function requireLogin() {
    if (!isLoggedIn()) {
        header('Location: login.php');
        exit;
    }
}

function getCurrentUser() {
    if (!isLoggedIn()) {
        return null;
    }
    
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
    $stmt->execute([$_SESSION['user_id']]);
    return $stmt->fetch();
}

// Использование
requireLogin();
$user = getCurrentUser();
?>

Выход из системы

Код:
<?php
session_start();

function logout() {
    $_SESSION = array();
    
    if (isset($_COOKIE[session_name()])) {
        setcookie(session_name(), '', time() - 3600, '/');
    }
    
    session_destroy();
}

if (isset($_GET['logout'])) {
    logout();
    header('Location: login.php');
    exit;
}
?>

Защита от CSRF

Код:
<?php
session_start();

function generateCSRFToken() {
    if (!isset($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

function validateCSRFToken($token) {
    return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}

// В форме
$csrfToken = generateCSRFToken();
echo '<input type="hidden" name="csrf_token" value="' . $csrfToken . '">';

// При обработке
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    if (!validateCSRFToken($_POST['csrf_token'])) {
        die('CSRF token validation failed');
    }
    // Обработка формы
}
?>

Защита от брутфорса

Код:
<?php
function checkLoginAttempts($username, $maxAttempts = 5, $lockoutTime = 300) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    // Удаление старых попыток
    $stmt = $pdo->prepare("DELETE FROM login_attempts WHERE username = ? AND time < ?");
    $stmt->execute([$username, time() - $lockoutTime]);
    
    // Подсчет попыток
    $stmt = $pdo->prepare("SELECT COUNT(*) as count FROM login_attempts WHERE username = ?");
    $stmt->execute([$username]);
    $result = $stmt->fetch();
    
    if ($result['count'] >= $maxAttempts) {
        return false; // Заблокирован
    }
    
    return true;
}

function recordLoginAttempt($username, $success) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    if (!$success) {
        $stmt = $pdo->prepare("INSERT INTO login_attempts (username, time, ip) VALUES (?, ?, ?)");
        $stmt->execute([$username, time(), $_SERVER['REMOTE_ADDR']]);
    }
}

// Использование
if (!checkLoginAttempts($username)) {
    die('Слишком много попыток входа. Попробуйте позже.');
}

$loginSuccess = loginUser($username, $password);
recordLoginAttempt($username, $loginSuccess);
?>

Запоминание пользователя (Remember Me)

Код:
<?php
function setRememberMe($userId) {
    $token = bin2hex(random_bytes(32));
    $expires = time() + (30 * 24 * 60 * 60); // 30 дней
    
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    $stmt = $pdo->prepare("INSERT INTO remember_tokens (user_id, token, expires) VALUES (?, ?, ?)");
    $stmt->execute([$userId, hash('sha256', $token), $expires]);
    
    setcookie('remember_token', $token, $expires, '/', '', true, true);
}

function checkRememberMe() {
    if (!isset($_COOKIE['remember_token'])) {
        return false;
    }
    
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    $tokenHash = hash('sha256', $_COOKIE['remember_token']);
    
    $stmt = $pdo->prepare("SELECT user_id FROM remember_tokens WHERE token = ? AND expires > ?");
    $stmt->execute([$tokenHash, time()]);
    $result = $stmt->fetch();
    
    if ($result) {
        $_SESSION['user_id'] = $result['user_id'];
        return true;
    }
    
    return false;
}

// При входе
if (isset($_POST['remember_me'])) {
    setRememberMe($userId);
}

// При загрузке страницы
if (!isLoggedIn()) {
    checkRememberMe();
}
?>

Сброс пароля

Код:
<?php
function generateResetToken($email) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch();
    
    if (!$user) {
        return false; // Не показываем что email не существует
    }
    
    $token = bin2hex(random_bytes(32));
    $expires = time() + 3600; // 1 час
    
    $stmt = $pdo->prepare("INSERT INTO password_resets (user_id, token, expires) VALUES (?, ?, ?)");
    $stmt->execute([$user['id'], hash('sha256', $token), $expires]);
    
    // Отправка email с токеном
    $resetLink = "https://example.com/reset-password.php?token=" . $token;
    mail($email, "Сброс пароля", "Перейдите по ссылке: " . $resetLink);
    
    return true;
}

function resetPassword($token, $newPassword) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    $tokenHash = hash('sha256', $token);
    $stmt = $pdo->prepare("SELECT user_id FROM password_resets WHERE token = ? AND expires > ?");
    $stmt->execute([$tokenHash, time()]);
    $result = $stmt->fetch();
    
    if (!$result) {
        return false;
    }
    
    $hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT);
    $stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
    $stmt->execute([$hashedPassword, $result['user_id']]);
    
    // Удаление токена
    $stmt = $pdo->prepare("DELETE FROM password_resets WHERE token = ?");
    $stmt->execute([$tokenHash]);
    
    return true;
}
?>

Двухфакторная аутентификация

Код:
<?php
function generate2FACode($userId) {
    $code = rand(100000, 999999);
    $expires = time() + 300; // 5 минут
    
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    $stmt = $pdo->prepare("INSERT INTO 2fa_codes (user_id, code, expires) VALUES (?, ?, ?)");
    $stmt->execute([$userId, $code, $expires]);
    
    // Отправка кода (email/SMS)
    return $code;
}

function verify2FACode($userId, $code) {
    $pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
    
    $stmt = $pdo->prepare("SELECT id FROM 2fa_codes WHERE user_id = ? AND code = ? AND expires > ?");
    $stmt->execute([$userId, $code, time()]);
    $result = $stmt->fetch();
    
    if ($result) {
        // Удаление использованного кода
        $stmt = $pdo->prepare("DELETE FROM 2fa_codes WHERE id = ?");
        $stmt->execute([$result['id']]);
        return true;
    }
    
    return false;
}
?>

Валидация данных

Код:
<?php
function validateRegistration($username, $email, $password) {
    $errors = [];
    
    // Валидация имени пользователя
    if (empty($username) || strlen($username) < 3) {
        $errors[] = "Имя пользователя должно быть не менее 3 символов";
    }
    if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
        $errors[] = "Имя пользователя может содержать только буквы, цифры и подчеркивание";
    }
    
    // Валидация email
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = "Неверный формат email";
    }
    
    // Валидация пароля
    if (strlen($password) < 8) {
        $errors[] = "Пароль должен быть не менее 8 символов";
    }
    if (!preg_match('/[A-Z]/', $password)) {
        $errors[] = "Пароль должен содержать хотя бы одну заглавную букву";
    }
    if (!preg_match('/[0-9]/', $password)) {
        $errors[] = "Пароль должен содержать хотя бы одну цифру";
    }
    
    return $errors;
}
?>

Система аутентификации - основа безопасности веб-приложений. Эти примеры показывают все необходимые компоненты для безопасной работы с пользователями.
 

1 человек читают эту тему (Всего: 1, Пользователей: 0, Гостей: 1)

Сверху