User login class in php

Простая аутентификация на PHP

Многие новички до сих пор попадают в тупик при написании простейшей аутентификации в PHP. На Тостере с завидной регулярностью попадаются вопросы о том, как сравнить сохраненный пароль с паролем полученным из формы логина. Здесь будет краткая статья-туториал на эту тему.

Disclaimer: статья рассчитана на совершенных новичков. Умудрённые опытом разработчики ничего нового здесь не найдут, но могут указать на возможные недочёты =).

Для написания системы аутентификации будем использовать базу данных MySQL/MariaDB, PHP, PDO, функции для работы с паролями, для построения интерфейса возьмём bootstrap.

Для начала создадим базу. Пусть она называется php-auth-demo. В новой базе создадим таблицу пользователей users :

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

Создадим конфиг с данными для подключения к базе.

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

 'php-auth-demo', 'db_host' => '127.0.0.1', 'db_user' => 'mysql', 'db_pass' => 'mysql', ];

И сделаем «загрузочный» файл, который будем подключать вначале всех остальных файлов.

В реальных проектах обычно используется автозагрузка необходимых файлов. Но этот момент выходит за рамки статьи, и в демо-примере мы обойдёмся простым подключением.

В «загрузочном» файле мы будем инициализировать сессию и объявим некоторые функции-помощники.

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); > return $pdo; >

Функция pdo() даст нам доступ к объекту PDO в любом месте нашего кода.

Далее нам нужна форма регистрации. Разместим её прямо в файле index.php .

 

Здесь всё просто: два поля, кнопка и форма, отправляющая запрос на файл do_register.php методом POST. Процесс регистрации пользователя опишем в файле do_register.php .

prepare("SELECT * FROM `users` WHERE `username` = :username"); $stmt->execute(['username' => $_POST['username']]); if ($stmt->rowCount() > 0) < flash('Это имя пользователя уже занято.'); header('Location: /'); // Возврат на форму регистрации die; // Остановка выполнения скрипта >// Добавим пользователя в базу $stmt = pdo()->prepare("INSERT INTO `users` (`username`, `password`) VALUES (:username, :password)"); $stmt->execute([ 'username' => $_POST['username'], 'password' => password_hash($_POST['password'], PASSWORD_DEFAULT), ]); header('Location: login.php');

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

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

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

В приведённом выше коде мы использовали функцию flash() . Данная функция предназначена для «одноразовых» сообщений. Если вызвать её со строковым параметром, то она сохранит эту строку в сессии, а если вызвать без параметров, то выведет из сессии сохранённое сообщение и затем удалит его в сессии. Добавим эту функцию в файл boot.php .

function flash(?string $message = null) < if ($message) < $_SESSION['flash'] = $message; >else < if (!empty($_SESSION['flash'])) < ?>  unset($_SESSION['flash']); > >

А также вызовем её нa форме регистрации, для вывода возможных сообщений.

На данном этапе простейший функционал регистрации нового пользователя готов.

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

Login

Register

В виду простоты примера, она практически повторяет форму регистрации. Интереснее будет посмотреть на сам процесс логина в файле do_login.php .

prepare("SELECT * FROM `users` WHERE `username` = :username"); $stmt->execute(['username' => $_POST['username']]); if (!$stmt->rowCount()) < flash('Пользователь с такими данными не зарегистрирован'); header('Location: login.php'); die; >$user = $stmt->fetch(PDO::FETCH_ASSOC); // проверяем пароль if (password_verify($_POST['password'], $user['password'])) < // Проверяем, не нужно ли использовать более новый алгоритм // или другую алгоритмическую стоимость // Например, если вы поменяете опции хеширования if (password_needs_rehash($user['password'], PASSWORD_DEFAULT)) < $newHash = password_hash($_POST['password'], PASSWORD_DEFAULT); $stmt = pdo()->prepare('UPDATE `users` SET `password` = :password WHERE `username` = :username'); $stmt->execute([ 'username' => $_POST['username'], 'password' => $newHash, ]); > $_SESSION['user_id'] = $user['id']; header('Location: /'); die; > flash('Пароль неверен'); header('Location: login.php');

Здесь есть важный момент. Мы не запрашиваем пользователя из таблицы по паре username/password, а используем только username. Дело в том, что даже если вы захешируете пришедший из формы логина пароль и попробуете сравнить новый хеш с сохранённым в базе, вы ничего не получите. Password_hash() использует автоматически генерируемую соль для паролей и хеши будут всегда получаться разные. Вот результат функции password_hash , вызванной несколько раз для пароля «123»:

$2y$10$loqucup11.3DL1fgDWanoettFpFJuFFd0fY6BZyiP698ZqvA4tmuy $2y$10$.LF3OzmQRtJvuZZWeWF.2u80x3ls6OEAU5J9gLHDtcYrFzJkRRPvq $2y$10$iGj/nOCavShd2vbMZTC4GOMYCqDj2YSc8qWoeqjVbD1xaKU2CgAfi

Именно поэтому необходимо использовать функцию password_verify для проверки пароля. Кроме того, данная функция использует специальный алгоритм проверки и является безопасной для атак по времени.

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

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

Для проверки того факта, что пользователь залогинен, нужно будет проверить наличие данного идентификатора в сессии. Мы для удобства напишем функцию-помощник и разместим ее в том же файле boot.php .

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

prepare("SELECT * FROM `users` WHERE `id` = :id"); $stmt->execute(['id' => $_SESSION['user_id']]); $user = $stmt->fetch(PDO::FETCH_ASSOC); > ?> 

Welcome back, !

else < ?>

Registration

?>

А также закрыть доступ к форме логина, если пользователь уже вошёл:

Осталось добавить возможность «выйти». Форму для выхода вы можете видеть в коде выше. Сама процедура выхода простейшая, и заключается в очистке сессии.

Заключение

  • Используем PDO/MySQLi и подготовленные запросы для работы с базой данных.
  • В базе данных обязательно храним только хеш пароля.
  • Для хеширования пароля используем специальную функцию password_hash.
  • Для проверки пароля не делаем сравнение хешей, а используем специальную функцию password_verify.

Полный код примера доступен на гитхабе: ссылка на Github.

Источник

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

PHP OOP design with injection safe PDO MySQL queries, this is an easy to read class for a user registration, login and logout system

License

cp6/Simple-PHP-user-register-and-login-class

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

Simple PHP user register and login class

PHP OOP design with injection safe PDO MySQL queries, this is an easy to read class for a user registration, login, authentication and logout system.

This code is bare bone with no front-end design or usage aside from basic registration, login, logout and an account page that can only be viewed when logged in.

  • PDO MySQL pre-prepared queries (injection proof).
  • Password hashing.
  • Lock IP address from login attempt after certain amount of fails in X time.
  • Honey pot login and registration form to prevent bots.
  • Secure session management for user authentication.
  • Login and register page cannot be viewed when logged in.
  • Only 2 lines to check if user is logged in or not, redirect if not.
  • Login attempt failed message suppression. Presents brute force and username guessing.
  • Usage of PHPMailer for account activation emails.
  1. Copy contents to working web directory.
  2. Run authdb.sql into MySQL.
  3. Edit class.php : configAndConnect
  • Add website name and url.
  • Edit failed attempts allowed, lock time and if accounts need activation via email.
  • Add Email SMTP details (If using account email activation)
  • Add MySQL database connection details

Ensure the class is called on your page (with relevant directory depth)

require_once('class.php'); //or require_once('../class.php');

Protecting page:

To protect a page, user must be logged in to view:

$session = new sessionManage(); $logged_in = $session->checkIsLoggedIn(true, '' . configAndConnect::URL . 'login/'); //Page content. 

If the session is not set which means the user isn’t logged in they will be directed to the websites login page.

View account/index.php for an example along with account data fetching.

The session is the users uid (id). If you want to fetch data like posts for the user define the uid as being the session:

About

PHP OOP design with injection safe PDO MySQL queries, this is an easy to read class for a user registration, login and logout system

Источник

Читайте также:  Contacts
Оцените статью