Формы авторизации и регистрации

Аутентификация

Представим интернет-магазин. Все его страницы можно разделить на две половины: публичные и приватные.

К публичным относятся страницы каталога, информации о товаре, условия доставки и так далее. К приватным — корзина покупок, история заказов. Совершенно очевидно, что корзина покупок у каждого покупателя должна быть своя, а иметь к ней доступ должен только сам владелец и никто больше.

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

  1. При попытке доступа к закрытой части сайта, пользователь видит форму ввода логина и пароля.
  2. Форма отправляется, а полученные данные сравниваются с действительным логином и паролем существующего пользователя. Эта сверка и называется аутентификацей.
  3. Если данные совпадают, то пользователь считается аутентифицированным и процесс авторизации продолжается. Пользователю выдаётся роль и связанные с ней права, в том числе получает доступ к приватной части сайта.
  4. При повторном открытии этой страницы пользователь не должен повторно вводить пароль, если он уже делал это в рамках текущего сеанса.

Отличие аутентификации и авторизации

Следует различать два термина: аутентификация и авторизация.

Аутентификация — проверка подлинности предоставленного пользователем удостоверяющей информации: пары логин-пароль. И проверка наличия учётной записи с такими данными

Авторизация — Это связывание сессии пользователя с определённой учётной записью и выдача прав соответствующих роли данной учётной записи.

Аутентификация – это лишь часть процесса авторизации. Аутентификация – это проверка данных. А авторизация – выдача прав определённой роли.

Таблица пользователей

CREATE TABLE `users` (
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
    `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `name` (`name`)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;

Начальный загрузчик

Роль начального загрузчика у нас выполняет файл setting.php или core.php. Который стартует сессию и создаёт подключение к БД и записывает это подключение в переменную $pdo.

Форма регистрации

Этот html размещаем в файле register.php

<?require_once __DIR__.'/setting.php';?>
require_once($setting['TEMPLATE_PATH'] . 'head.php');?>

<body>
	<?require_once($setting['TEMPLATE_PATH'] . 'header.php');?>
<div class="error" <?if (empty($error['register'])) {?>style="display: none;"<?}?>>
<?foreach($error['register'] as $message) {?>
    <p><?=$message;?></p>
<?}?>
</div>

<?if ($success['register']) {?>
    <p><?=$success['register'];?></p>
<?} else {?>
<form action="/form/do_reg.php" method="POST">
    <input type="text" name="login" placeholder="Login" />
    <input type="text" name="name" placeholder="Name"/>
    <input type="email" name="email" placeholder="Email Address"/>
    <input type="password" name="password" placeholder="Password"/>
    <button type="submit" class="btn btn-default">Регистрация</button>
</form>
<?}?>

Обработка регистрации

Напишем обработчик, файл do_reg.php

<?php require_once('../setting.php');

$error = ['register' => []];
$success = ['register' => false];

if (isset($_POST['login']) && !$_POST['login']) {
    $error['register'][] = 'Пустой логин';
}

// Проверим, не занято ли имя пользователя
$stmt = $pdo->prepare("SELECT * FROM `wshop_user` WHERE `login` = :login");
$stmt->execute(['login' => $_POST['login']]);
if ($stmt->rowCount() > 0) {
    $error['register'][] = 'Это имя пользователя уже занято.';
}

if (empty($error['register'])) {
    // Добавим пользователя в базу
    $stmt = $pdo->prepare("INSERT INTO `wshop_user` (`login`, `password`, `name`, `role_id`) VALUES (:login, :password, :name, 3)");
    $stmt->execute([
        'login' => $_POST['login'],
        'password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
        'name' => $_POST['name'],
    ]);
    
    $success['register'] = 'Пользователь зарегистрирован';
}

require('../page/login.php');

В самом начале подключим наш “загрузчик”.

Потом проверим, не занято ли имя пользователя. Для этого сделаем выборку из таблицы указав в условии полученное из формы имя пользователя. Обратите внимание, для запросов здесь и далее мы будем использовать подготовленные запросы, что обезопасит нас от SQL-инъекций. Для этого в тексте SQL-запроса мы указываем специальные плейсхолдеры, а при выполнении ассоциируем с ними ненадёжные данные (ненадёжными данными следует считать всё, что приходит из вне – $_GET, $_POST, $_REQUEST, $_COOKIE). После выполнения запроса мы просто проверим количество возвращённых строк. Если их больше нуля, то имя пользователя уже занято. В этом случае мы выведем сообщение и вернём пользователя на форму регистрации.

Написано “больше нуля”, но по факту, из-за того, что поле name в таблице уникальное, rowCount() может нам вернуть лишь два возможных значения: 0 и 1.

Форма авторизации

Этот html размещаем в файле login.php

<?require_once __DIR__.'/setting.php';?>
require_once($setting['TEMPLATE_PATH'] . 'head.php');?>

<body>
    <?require_once($setting['TEMPLATE_PATH'] . 'header.php');?>
    <div class="error" <?if (empty($error['login'])) {?>style="display: none;"<?}?>>
    <?foreach($error['login'] as $message) {?>
        <p><?=$message?></p>
    <?}?>
    </div>
    
    <form action="/form/do_login.php" method="POST">
        <input type="text" name="login" placeholder="Login" />
        <input type="password" name="password" placeholder="Password"/>
        <span>
            <input type="checkbox" class="checkbox"> 
            Запомнить меня
        </span>
        <button type="submit" class="btn btn-default">Войти</button>
    </form>

Обработка авторизации

<?require_once('../setting.php');

$error = ['login' => []];
if (isset($_POST['login']) && !$_POST['login']) {
    $error['login'][] = 'Пустой логин';
} elseif (isset($_POST['login'])) {
    // проверяем наличие пользователя с указанным юзернеймом
    $stmt = $pdo->prepare("SELECT * FROM `wshop_user` WHERE `login` = :login");
    $stmt->execute(['login' => $_POST['login']]);
    if (!$stmt->rowCount()) {
        $error['login'][] = 'Пользователь с такими данными не зарегистрирован';
    } else {
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        // проверяем пароль
        // $error['login'][] =  $_POST['password'] . ' - ' . $user['password'];
        if (password_verify($_POST['password'], $user['password'])) {
            unset($user['password']);
            $_SESSION['user'] = $user;
            // лучше перекинуть в ЛК /page/account/
            header('Location: /');
            die;
        } else {
            $error['login'][] = 'Пароль неверен';
        }
    }
}

require('../page/login.php');

Использование сессии для контроля доступа

Сессии чаще всего используются для хранения информации о залогиненном пользователе.

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

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

Если сессия пуста, значит, пользователь не выполнял вход на сайт и доступа к данной странице не имеет. В этом случае можно вернуть код ответа 403 и показать сообщение об ошибке.

Задача

1 создайте формы авторизации и регистрации убедитесь, что они работают.

2 Напишите форму и обработчик оформления заказа.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *