Регистрация и авторизация в php с JSON Web Token
Сегодня мы реализуем форму регистрации, входа, выхода и обновления учётной записи пользователя, используя JSON Web Token.
- Что такое JWT?
- Файловая структура
- Настройка базы данных
- Создание API для регистрации пользователей
- Создание API для входа пользователей
- Создание API для валидации JWT
- Создание API для учетных записей пользователей
- Создание интерфейса для регистрации пользователей
- Создание интерфейса для входа пользователей
- Создание интерфейса домашней страницы
- Создание интерфейса для страницы аккаунта
1. Что такое JWT
JWT (JSON Web Token) — это формат упаковки данных, который позволяет обеспечить безопасную передачу информации между клиентом и сервером в JSON-формате.
Токены будут создаваться на сервере, подписываться секретным ключом с последующей передачей клиенту для подтверждения своей личности.
Информация будет надёжно защищена, т.к. она будет иметь цифровую подпись.
Пример: сервер генерирует токен «пользователь вошёл как администратор» и предоставляет его клиенту. Затем клиент использует этот токен для доказательства того, он он вошёл «как администратор».
2. Файловая структура
- authentication-jwt/
- api/
- Config/
- Core.php
- Database.php
- libs/
- php-jwt/
- Objects/
- User.php
- create_user.php
- login.php
- update_user.php
- validate_token.php
- Config/
- custom.css
- index.html
- api/
3. Настройка базы данных
Создадим базу данных authentication_jwt, а в ней таблицу users.
Таблица следующего вида:

-- phpMyAdmin SQL Dump
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
--
-- База данных: `api_db`
--
-- --------------------------------------------------------
--
-- Структура таблицы `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`firstname` varchar(256) NOT NULL,
`lastname` varchar(256) NOT NULL,
`email` varchar(256) NOT NULL,
`password` varchar(2048) NOT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;COMMIT;
Создадим папку для проекта authentication-jwt.
Я буду использовать OpenServer, поэтому папку проекта я создам в следующей директории:
D:\OSPanel\domains\authentication-jwt\
После того как у вас структура подготовлена (смотрите п.2), откроем файл Database.php в папке api/Config/ — файл для соединения с базой данных.
Добавим в него следующий код:
<?php
// Используем для подключения к базе данных MySQL
class Database
{
// Учётные данные базы данных
private $host = "localhost";
private $db_name = "authentication_jwt";
private $username = "root";
private $password = "root";
public $conn;
// Получаем соединение с базой данных
public function getConnection()
{
$this->conn = null;
try {
$this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
} catch (PDOException $exception) {
echo "Ошибка соединения с БД: " . $exception->getMessage();
}
return $this->conn;
}
}
4. Создание API для регистрации пользователей
Нам нужно установить заголовки, чтобы файл для создания пользователей принимал только данные JSON
В папке api в файл сreate_user.php добавим следующий код.
<?php
// Заголовки
header("Access-Control-Allow-Origin: http://authentication-jwt/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// Подключение к БД
// Файлы, необходимые для подключения к базе данных
include_once "./Config/Database.php";
include_once "../Objects/User.php";
// Получаем соединение с базой данных
$database = new Database();
$db = $database->getConnection();
// Создание объекта "User"
$user = new User($db);
// Отправляемые данные будут здесь
Информация о пользователе будет отправлена через HTML-форму и JavaScript код. Мы увидим это позже. Нам необходимо назначить отправляемые данные в свойствах объекта, такие как имя, фамилия и т.п.
Замените комментарий // Отправляемые данные будут здесь в файле сreate_user.php следующим кодом:
// Получаем данные
$data = json_decode(file_get_contents("php://input"));
// Устанавливаем значения
$user->firstname = $data->firstname;
$user->lastname = $data->lastname;
$user->email = $data->email;
$user->password = $data->password;
// Поверка на существование e-mail в БД
// $email_exists = $user->emailExists();
// Здесь будет метод create()
Мы будем использовать метод create(), который сообщит нам о том, был создан пользователь или нет.
Замените комментарий // Здесь будет метод create() в файле create_user.php следующим кодом:
// Создание пользователя
if (
!empty($user->firstname) &&
!empty($user->email) &&
// $email_exists == 0 &&
!empty($user->password) &&
$user->create()
) {
// Устанавливаем код ответа
http_response_code(200);
// Покажем сообщение о том, что пользователь был создан
echo json_encode(array("message" => "Пользователь был создан"));
}
// Сообщение, если не удаётся создать пользователя
else {
// Устанавливаем код ответа
http_response_code(400);
// Покажем сообщение о том, что создать пользователя не удалось
echo json_encode(array("message" => "Невозможно создать пользователя"));
}
Создание класса User
Предыдущий файл не будет работать без класса User.
Откройте api/Objects/User.php и внесите следующий код:
<?php
class User
{
// Подключение к БД таблице "users"
private $conn;
private $table_name = "users";
// Свойства
public $id;
public $firstname;
public $lastname;
public $email;
public $password;
// Конструктор класса User
public function __construct($db)
{
$this->conn = $db;
}
// Метод для создания нового пользователя
function create()
{
// Запрос для добавления нового пользователя в БД
$query = "INSERT INTO " . $this->table_name . "
SET
firstname = :firstname,
lastname = :lastname,
email = :email,
password = :password";
// Подготовка запроса
$stmt = $this->conn->prepare($query);
// Инъекция
$this->firstname = htmlspecialchars(strip_tags($this->firstname));
$this->lastname = htmlspecialchars(strip_tags($this->lastname));
$this->email = htmlspecialchars(strip_tags($this->email));
$this->password = htmlspecialchars(strip_tags($this->password));
// Привязываем значения
$stmt->bindParam(":firstname", $this->firstname);
$stmt->bindParam(":lastname", $this->lastname);
$stmt->bindParam(":email", $this->email);
// Для защиты пароля
// Хешируем пароль перед сохранением в базу данных
$password_hash = password_hash($this->password, PASSWORD_BCRYPT);
$stmt->bindParam(":password", $password_hash);
// Выполняем запрос
// Если выполнение успешно, то информация о пользователе будет сохранена в базе данных
if ($stmt->execute()) {
return true;
}
return false;
}
// Здесь будет метод emailExists()
}
Тестирование API
Можно использовать POSTMAN для тестирования нашего API. Скачать его можно здесь.
Сначала мы проверим успешность создания пользователя. Запустим POSTMAN.
Нажмите Collections, далее +, метод запроса POST и введите следующий URL запрос:
http://authentication-jwt/api/create_user.php
Нажмите Body, затем raw и вставьте следующее значение JSON.
{
"firstname" : "Vasiliy",
"lastname" : "Ivanov",
"email" : "vasya@coder.com",
"password" : "888"
}
Нажмите кнопку Send. Если сделали верно, должны увидеть следующее:

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

5. Создание API для входа пользователей
В приведенном ниже коде установим заголовки, чтобы файл знал откуда должен поступить запрос и какой тип данных принимается.
Откроем файл api/login.php и поместим в него следующий код.
<?php
// Заголовки
header("Access-Control-Allow-Origin: http://authentication-jwt/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// Здесь будет соединение с БД
Мы сравним электронную почту пользователя и пароль из базы данных, поэтому нам нужно подключение к БД.
Нам также нужно создать экземпляр пользовательской таблицы, это позволит нам проверить, существует ли электронная почта, и прочитать хешированный пароль.
Замените комментарий // Здесь будет соединение с БД в файле login.php следующим кодом:
// Файлы необходимые для соединения с БД
include_once "./Config/Database.php";
include_once "../Objects/User.php";
// Получаем соединение с базой данных
$database = new Database();
$db = $database->getConnection();
// Создание объекта "User"
$user = new User($db);
// Получаем данные
$data = json_decode(file_get_contents("php://input"));
// Устанавливаем значения
$user->email = $data->email;
$email_exists = $user->emailExists();
// Файлы для JWT будут здесь
Проверка на существование e-mail
Добавим метод emailExists() в наш класс User.
Этот метод вернёт истину (true), если отправленный e-mail существует, иначе вернёт ложь (false).
Замените комментарий // Здесь будет метод emailExists() в файле /api/Objects/User.php следующим кодом.
// Проверка, существует ли электронная почта в нашей базе данных
function emailExists() {
// Запрос, чтобы проверить, существует ли электронная почта
$query = "SELECT id, firstname, lastname, password
FROM " . $this->table_name . "
WHERE email = ?
LIMIT 0,1";
// Подготовка запроса
$stmt = $this->conn->prepare($query);
// Инъекция
$this->email=htmlspecialchars(strip_tags($this->email));
// Привязываем значение e-mail
$stmt->bindParam(1, $this->email);
// Выполняем запрос
$stmt->execute();
// Получаем количество строк
$num = $stmt->rowCount();
// Если электронная почта существует,
// Присвоим значения свойствам объекта для легкого доступа и использования для php сессий
if ($num > 0) {
// Получаем значения
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// Присвоим значения свойствам объекта
$this->id = $row["id"];
$this->firstname = $row["firstname"];
$this->lastname = $row["lastname"];
$this->password = $row["password"];
// Вернём "true", потому что в базе данных существует электронная почта
return true;
}
// Вернём "false", если адрес электронной почты не существует в базе данных
return false;
}
// Здесь будет метод update()
Создание JWT (JSON web token)
Заменим комментарий // Файлы для JWT будут здесь в файле api/login.php на следующий код:
// Подключение файлов JWT
include_once "config/core.php";
include_once "libs/php-jwt/BeforeValidException.php";
include_once "libs/php-jwt/ExpiredException.php";
include_once "libs/php-jwt/SignatureInvalidException.php";
include_once "libs/php-jwt/JWT.php";
use \Firebase\JWT\JWT;
// Существует ли электронная почта и соответствует ли пароль тому, что находится в базе данных
if ($email_exists && password_verify($data->password, $user->password)) {
$token = array(
"iss" => $iss,
"aud" => $aud,
"iat" => $iat,
"nbf" => $nbf,
"data" => array(
"id" => $user->id,
"firstname" => $user->firstname,
"lastname" => $user->lastname,
"email" => $user->email
)
);
// Код ответа
http_response_code(200);
// Создание jwt
$jwt = JWT::encode($token, $key, 'HS256');
echo json_encode(
array(
"message" => "Успешный вход в систему",
"jwt" => $jwt
)
);
}
// Если электронная почта не существует или пароль не совпадает,
// Сообщим пользователю, что он не может войти в систему
else {
// Код ответа
http_response_code(401);
// Скажем пользователю что войти не удалось
echo json_encode(array("message" => "Ошибка входа"));
}
?>
Создание файла конфигурации (ядра)
Файл login.php не будет работать без файла core.php. Этот файл содержит общие настройки / переменные нашего приложения.
У нас есть переменные, используемые нашей библиотекой JWT для кодирования и декодирования токена. Значение $key должно быть вашим собственным и уникальным секретным ключом.
- iss — адрес или имя удостоверяющего центра;
- aud — имя клиента для которого токен выпущен;
- iat — время, когда был выпущен JWT;
- nbf — время, начиная с которого может быть использован (не раньше, чем).
Вы также можете использовать exp — идентифицирует время истечения срока действия токена.
Откроем api/config/core.php и добавим следующий код.
<?php
// Показ сообщений об ошибках
error_reporting(E_ALL);
// Установим часовой пояс по умолчанию
date_default_timezone_set("Europe/Moscow");
// Переменные, используемые для JWT
$key = "your_secret_key";
$iss = "http://any-site.org";
$aud = "http://any-site.com";
$iat = 1356999524;
$nbf = 1357000000;
Скачайте библиотеку PHP-JWT c GitHub’а.
Скопируйте содержимое библиотеки в api/libs/.
Тест входа в систему
Введём следующий URL запрос:
http://authentication-jwt/api/login.php
В Body вставьте следующее значение JSON.
{
"email" : "vasya@coder.com",
"password" : "888"
}
Нам нужно сохранить сгенерированный JWT чтобы потом его использовать для проверки.

Для проверки на неудачный вход в систему измените значение пароля на 222 (это неверный пароль).

6. Создание API для валидации JWT
Приступим к наполнению файла api/validate_token.php.
Установим правильные заголовки. Этот файл вернет вывод в формате JSON и примет запросы от указанного URL.
<?php
// Заголовки
header("Access-Control-Allow-Origin: http://localhost/rest-api-authentication-example/");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// Требуется для декодирования JWT
include_once "config/core.php";
include_once "libs/php-jwt/BeforeValidException.php";
include_once "libs/php-jwt/ExpiredException.php";
include_once "libs/php-jwt/SignatureInvalidException.php";
include_once "libs/php-jwt/JWT.php";
include_once "libs/php-jwt/Key.php";
use \Firebase\JWT\JWT;
use \Firebase\JWT\Key;
// Получаем значение веб-токена JSON
$data = json_decode(file_get_contents("php://input"));
// Получаем JWT
$jwt = isset($data->jwt) ? $data->jwt : "";
// Если JWT не пуст
if ($jwt) {
// Если декодирование выполнено успешно, показать данные пользователя
try {
// Декодирование jwt
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
// Код ответа
http_response_code(200);
// Покажем детали
echo json_encode(array(
"message" => "Доступ разрешен",
"data" => $decoded->data
));
}
// Если декодирование не удалось, это означает, что JWT является недействительным
catch (Exception $e) {
// Код ответа
http_response_code(401);
// Сообщим пользователю что ему отказано в доступе и покажем сообщение об ошибке
echo json_encode(array(
"message" => "Вам доступ закрыт",
"error" => $e->getMessage()
));
}
}
// Покажем сообщение об ошибке, если JWT пуст
else {
// Код ответа
http_response_code(401);
// Сообщим пользователю что доступ запрещен
echo json_encode(array("message" => "Доступ запрещён"));
}
Тест на успешный доступ
Введём следующий URL:
http://authentication-jwt/api/validate_token.php
Введите JSON токен, который вы получили ранее. Приведенный ниже токен JSON отличается от вашего.
{
"jwt" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxMzU2OTk5NTI0LCJuYmYiOjEzNTcwMDAwMDAsImRhdGEiOnsiaWQiOiIyIiwiZmlyc3RuYW1lIjoiVmFzaWxpeSIsImxhc3RuYW1lIjoiSXZhbm92IiwiZW1haWwiOiJ2YXN5YUBjb2Rlci5jb20ifX0.W4ghyd6D4jRAnOeiT4-wTjdjaGh9EYmJDlssrai6A80"
}
Так должно выглядеть в POSTMAN:

Чтобы проверить наличие неудачного доступа, просто добавьте слово «EDITED» в свой JWT. Это сделает JWT неправильным и приведет к отказу в доступе. Это должно выглядеть так.

7. Создание API для учетных записей пользователей
Откроем api/update_user.php и вставим следующий код.
<?php
// Заголовки
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// Требуется для кодирования веб-токена JSON
include_once "config/core.php";
include_once "libs/php-jwt/BeforeValidException.php";
include_once "libs/php-jwt/ExpiredException.php";
include_once "libs/php-jwt/SignatureInvalidException.php";
include_once "libs/php-jwt/JWT.php";
include_once "libs/php-jwt/Key.php";
use \Firebase\JWT\JWT;
use \Firebase\JWT\Key;
// Файлы, необходимые для подключения к базе данных
include_once "./Config/Database.php";
include_once "../Objects/User.php";
// Получаем соединение с БД
$database = new Database();
$db = $database->getConnection();
// Создание объекта "User"
$user = new User($db);
// Получаем данные
$data = json_decode(file_get_contents("php://input"));
// Получаем jwt
$jwt = isset($data->jwt) ? $data->jwt : "";
// Если JWT не пуст
if ($jwt) {
// Если декодирование выполнено успешно, показать данные пользователя
try {
// Декодирование jwt
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
// Нам нужно установить отправленные данные (через форму HTML) в свойствах объекта пользователя
$user->firstname = $data->firstname;
$user->lastname = $data->lastname;
$user->email = $data->email;
$user->password = $data->password;
$user->id = $decoded->data->id;
// Создание пользователя
if ($user->update()) {
// сгенерировать заново JWT здесь
}
// Сообщение, если не удается обновить пользователя
else {
// Код ответа
http_response_code(401);
// Показать сообщение об ошибке
echo json_encode(array("message" => "Невозможно обновить пользователя"));
}
}
// Если декодирование не удалось, это означает, что JWT является недействительным
catch (Exception $e) {
// Код ответа
http_response_code(401);
// Сообщение об ошибке
echo json_encode(array(
"message" => "Доступ закрыт",
"error" => $e->getMessage()
));
}
}
// Показать сообщение об ошибке, если jwt пуст
else {
// Код ответа
http_response_code(401);
// Сообщить пользователю что доступ запрещен
echo json_encode(array("message" => "Доступ закрыт"));
}
Создание метода Update()
Выполним запрос UPDATE, очистку данных и привязку.
Замените комментарий // Здесь будет метод update() в файле api/Objects/User.php следующим кодом.
// Обновить запись пользователя
public function update() {
// Если в HTML-форме был введен пароль (необходимо обновить пароль)
$password_set=!empty($this->password) ? ", password = :password" : "";
// Если не введен пароль - не обновлять пароль
$query = "UPDATE " . $this->table_name . "
SET
firstname = :firstname,
lastname = :lastname,
email = :email
{$password_set}
WHERE id = :id";
// Подготовка запроса
$stmt = $this->conn->prepare($query);
// Инъекция (очистка)
$this->firstname=htmlspecialchars(strip_tags($this->firstname));
$this->lastname=htmlspecialchars(strip_tags($this->lastname));
$this->email=htmlspecialchars(strip_tags($this->email));
// Привязываем значения с HTML формы
$stmt->bindParam(":firstname", $this->firstname);
$stmt->bindParam(":lastname", $this->lastname);
$stmt->bindParam(":email", $this->email);
// Метод password_hash () для защиты пароля пользователя в базе данных
if(!empty($this->password)){
$this->password=htmlspecialchars(strip_tags($this->password));
$password_hash = password_hash($this->password, PASSWORD_BCRYPT);
$stmt->bindParam(":password", $password_hash);
}
// Уникальный идентификатор записи для редактирования
$stmt->bindParam(":id", $this->id);
// Если выполнение успешно, то информация о пользователе будет сохранена в базе данных
if($stmt->execute()) {
return true;
}
return false;
}
Повторная генерация JWT
Замените комментарий // Сгенерировать заново JWT здесь в файле api/update_user.php следующим кодом:
// Нам нужно заново сгенерировать JWT, потому что данные пользователя могут отличаться
$token = array(
"iss" => $iss,
"aud" => $aud,
"iat" => $iat,
"nbf" => $nbf,
"data" => array(
"id" => $user->id,
"firstname" => $user->firstname,
"lastname" => $user->lastname,
"email" => $user->email
)
);
$jwt = JWT::encode($token, $key, 'HS256');
// Код ответа
http_response_code(200);
// Ответ в формате JSON
echo json_encode(
array(
"message" => "Пользователь был обновлён",
"jwt" => $jwt
)
);
Тест успешного обновления пользователя
Введём следующий URL в POSTMAN.
http://authentication-jwt/api/update_user.php
В разделе Body изменим информацию о текущем пользователе с помощью веб-токена JSON, который мы получили ранее (и сохранили).
{
"firstname" : "Vasiliy",
"lastname" : "Ivanov",
"email" : "vasya2@coder.com",
"password" : "888",
"jwt" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxMzU2OTk5NTI0LCJuYmYiOjEzNTcwMDAwMDAsImRhdGEiOnsiaWQiOiIyIiwiZmlyc3RuYW1lIjoiVmFzaWxpeSIsImxhc3RuYW1lIjoiSXZhbm92IiwiZW1haWwiOiJ2YXN5YUBjb2Rlci5jb20ifX0.W4ghyd6D4jRAnOeiT4-wTjdjaGh9EYmJDlssrai6A80"
}
Должно выглядеть примерно так.

При обновлении информации о пользователе происходит генерация нового токена JWT.
Чтобы проверить, не удалось ли обновить пользователя, вы можете просто добавить слово EDITED в правленную JWT, или просто удалить JWT. Это должно выглядеть следующим образом.

8. Создание интерфейса для регистрации пользователей
Мы будем использовать API, которые мы создали ранее. Весь необходимый код будет в одном файле index.html с использованием HTML, CSS и JavaScript.
Откройте файл index.html или создайте, если ещё этого не сделали, в нашей папке authentication-jwt. Поместите следующий код:
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Пример REST API аутентификации</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
crossorigin="anonymous" />
<link rel="stylesheet" href="custom.css" />
</head>
<body>
<!-- Навигация -->
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
<a class="navbar-brand" href="#">Навигация</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup"
aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-item nav-link" href="javascript:void(0);" id="home">Домашняя страница</a>
<a class="nav-item nav-link" href="javascript:void(0);" id="update_account">Учетная запись</a>
<a class="nav-item nav-link" href="javascript:void(0);" id="logout">Выход</a>
<a class="nav-item nav-link" href="javascript:void(0);" id="login">Вход</a>
<a class="nav-item nav-link" href="javascript:void(0);" id="sign_up">Регистрация</a>
</div>
</div>
</nav>
<main role="main" class="container starter-template">
<div class="row">
<div class="col">
<!-- Здесь будут подсказки / быстрые сообщения -->
<div id="response"></div>
<!-- Здесь появится основной контент -->
<div id="content"></div>
</div>
</div>
</main>
<!-- jQuery & Bootstrap 4 JavaScript -->
<script src="http://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
<!-- Здесь будет jQuery код -->
</body>
</html>
Создадим файл custom.css который мы подключили в шапке, со следующим содержимым:
body { padding-top: 45px; }
.starter-template { padding: 35px 22px; }
#logout{ display:none; }
Показать HTML форму регистрации
Когда вы нажмёте на меню Регистрация на навигационной панели, отобразится форма регистрации.
Замените комментарий <!— Здесь будет jQuery код —> следующим кодом.
<script>
jQuery($ => {
// Показ формы регистрации
$(document).on("click", "#sign_up", () => {
let html = `
<h2>Регистрация</h2>
<form id="sign_up_form">
<div class="form-group">
<label for="firstname">Имя</label>
<input type="text" class="form-control" name="firstname" id="firstname" required />
</div>
<div class="form-group">
<label for="lastname">Фамилия</label>
<input type="text" class="form-control" name="lastname" id="lastname" required />
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" name="email" id="email" required />
</div>
<div class="form-group">
<label for="password">Пароль</label>
<input type="password" class="form-control" name="password" id="password" required />
</div>
<button type="submit" class="btn btn-primary">Зарегистрироваться</button>
</form>
`;
clearResponse();
$("#content").html(html);
});
// Выполнение кода при отправке формы
// Показать форму входа при клике на кнопку
// Удаление всех быстрых сообщений
function clearResponse() {
$("#response").html("");
}
// Функция showLoginPage()
// SerializeObject будет здесь
});
</script>
Нам нужно обработать данные формы, когда она будет отправлена.
Замените комментарий // Выполнение кода при отправке формы следующим кодом.
// Выполнение кода при отправке формы
$(document).on("submit", "#sign_up_form", function () {
// Получаем данные формы
const sign_up_form = $(this);
const form_data = JSON.stringify(sign_up_form.serializeObject());
// Отправка данных формы в API
$.ajax({
url: "api/create_user.php",
type: "POST",
contentType: "application/json",
data: form_data,
success: result => {
// В случае удачного завершения запроса к серверу,
// сообщим пользователю, что он успешно зарегистрировался и очистим поля ввода
$("#response").html("<div class='alert alert-success'>Регистрация завершена успешно. Пожалуйста, войдите</div>");
sign_up_form.find("input").val("");
},
error: (xhr, resp, text) => {
// При ошибке сообщить пользователю, что регистрация не удалась
$("#response").html("<div class='alert alert-danger'>Невозможно зарегистрироваться. Пожалуйста, свяжитесь с администратором</div>");
}
});
return false;
});
9. Создание интерфейса для входа пользователей
Если щёлкнуть на меню «Вход» на панели навигации, отобразится форма входа.
Замените комментарий // Показать форму входа при клике на кнопку следующим кодом.
// Показа формы входа
$(document).on("click", "#login", () => {
showLoginPage();
});
// При отправке формы входа
$(document).on("submit", "#login_form", function () {
// Получаем данные формы
const login_form = $(this);
const form_data = JSON.stringify(login_form.serializeObject());
// Отправка данных формы в API
$.ajax({
url: "api/login.php",
type: "POST",
contentType: "application/json",
data: form_data,
success: result => {
// Сохраним JWT в куки
setCookie("jwt", result.jwt, 1);
// Показ домашней страницы и сообщение об успешном входе
showHomePage();
$("#response").html("<div class='alert alert-success'>Успешный вход в систему.</div>");
},
error: (xhr, resp, text) => {
// При ошибке сообщим пользователю, что вход в систему не выполнен и очистим поля ввода
$("#response").html("<div class='alert alert-danger'>Ошибка входа. Email или пароль указан неверно.</div>");
login_form.find("input").val("");
}
});
return false;
});
// Показ домашней страницы
Замените комментарий // Функция showLoginPage() следующим кодом.
// Функция показывает HTML-форму для входа в систему.
function showLoginPage() {
// Удаление jwt
setCookie("jwt", "", 1);
// Форма входа
let html = `
<h2>Вход</h2>
<form id="login_form">
<div class="form-group">
<label for="email">Email адрес</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Введите email">
</div>
<div class="form-group">
<label for="password">Пароль</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Введите пароль">
</div>
<button type="submit" class="btn btn-primary">Войти</button>
</form>
`;
$("#content").html(html);
clearResponse();
showLoggedOutMenu();
}
// Функция setCookie() поможет нам сохранить JWT в файле cookie
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
// Эта функция сделает меню похожим на опции для пользователя, вышедшего из системы.
function showLoggedOutMenu() {
// Показать кнопку входа и регистрации в меню навигации
$("#login, #sign_up").show();
$("#logout").hide();
}
// Здесь будет функция showHomePage()
Замените комментарий // SerializeObject будет здесь следующим кодом.
// Функция для преобразования значений формы в формат JSON
$.fn.serializeObject = function () {
let o = {};
let a = this.serializeArray();
$.each(a, function () {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || "");
} else {
o[this.name] = this.value || "";
}
});
return o;
};
10. Создание интерфейса домашней страницы
Замените комментарий // Показ домашней страницы следующим кодом.
// Показать домашнюю страницу
$(document).on("click", "#home", () => {
showHomePage();
clearResponse();
});
// Показать форму обновления аккаунта
Замените комментарий // Здесь будет функция showHomePage() следующим кодом.
// Функция для показа домашней страницы
function showHomePage() {
// Валидация JWT для проверки доступа
const jwt = getCookie("jwt");
$.post("api/validate_token.php", JSON.stringify({ jwt: jwt })).done(result => {
// если прошел валидацию, показать домашнюю страницу
let html = `
<div class="card">
<div class="card-header">Добро пожаловать!</div>
<div class="card-body">
<h5 class="card-title">Вы вошли в систему</h5>
<p class="card-text">Вы не сможете получить доступ к домашней странице и страницам учетной записи, если вы не вошли в систему</p>
</div>
</div>
`;
$("#content").html(html);
showLoggedInMenu();
})
// Показать страницу входа при ошибке
.fail(function (result) {
showLoginPage();
$("#response").html("<div class='alert alert-danger'>Пожалуйста войдите, чтобы получить доступ к домашней станице</div>");
});
}
// Функция поможет нам прочитать JWT, который мы сохранили ранее.
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(";");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == " ") {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
// Если пользователь авторизован
function showLoggedInMenu() {
// Скроем кнопки входа и регистрации с панели навигации и покажем кнопку выхода
$("#login, #sign_up").hide();
$("#logout").show();
}
// Здесь будет функция showUpdateAccountForm()
11. Создание интерфейса для страницы аккаунта пользователя
Замените комментарий // Показать форму обновления аккаунта следующим кодом.
$(document).on("click", "#update_account", () => {
showUpdateAccountForm();
});
// срабатывание при отправке формы «обновить аккаунт»
$(document).on("submit", "#update_account_form", function () {
// Дескриптор для update_account_form
const update_account_form = $(this);
// Валидация JWT для проверки доступа
const jwt = getCookie("jwt");
// Получаем данные формы
let update_account_form_obj = update_account_form.serializeObject()
// Добавим JWT
update_account_form_obj.jwt = jwt;
// Преобразуем значения формы в JSON с помощью функции stringify()
const form_data = JSON.stringify(update_account_form_obj);
// Отправка данных формы в API
$.ajax({
url: "api/update_user.php",
type: "POST",
contentType: "application/json",
data: form_data,
success: result => {
// Сказать, что учетная запись пользователя была обновлена
$("#response").html("<div class='alert alert-success'>Учетная запись обновлена</div>");
// Сохраняем новый JWT в cookie
setCookie("jwt", result.jwt, 1);
},
// Показать сообщение об ошибке пользователю
error: (xhr, resp, text) => {
if (xhr.responseJSON.message == "Невозможно обновить пользователя") {
$("#response").html("<div class='alert alert-danger'>Невозможно обновить пользователя</div>");
}
else if (xhr.responseJSON.message == "Доступ закрыт") {
showLoginPage();
$("#response").html("<div class='alert alert-success'>Доступ закрыт. Пожалуйста войдите</div>");
}
}
});
return false;
});
// Выйти из системы
$(document).on("click", "#logout", () => {
showLoginPage();
$("#response").html("<div class='alert alert-info'>Вы вышли из системы.</div>");
});
Замените комментарий // Здесь будет функция showUpdateAccountForm() следующим кодом.
function showUpdateAccountForm() {
// Валидация JWT для проверки доступа
const jwt = getCookie("jwt");
$.post("api/validate_token.php", JSON.stringify({ jwt: jwt })).done(result => {
// Если валидация прошла успешно, покажем данные пользователя в форме
let html = `
<h2>Обновление аккаунта</h2>
<form id="update_account_form">
<div class="form-group">
<label for="firstname">Имя</label>
<input type="text" class="form-control" name="firstname" id="firstname" required value="${result.data.firstname}" />
</div>
<div class="form-group">
<label for="lastname">Фамилия</label>
<input type="text" class="form-control" name="lastname" id="lastname" required value="${result.data.lastname}" />
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" name="email" id="email" required value="${result.data.email}" />
</div>
<div class="form-group">
<label for="password">Пароль</label>
<input type="password" class="form-control" name="password" id="password" />
</div>
<button type="submit" class="btn btn-primary">
Сохранить
</button>
</form>
`;
clearResponse();
$("#content").html(html);
})
// В случае ошибки / сбоя сообщите пользователю, что ему необходимо войти в систему,
// чтобы увидеть страницу учетной записи
.fail(result => {
showLoginPage();
$("#response").html("<div class='alert alert-danger'>Пожалуйста, войдите, чтобы получить доступ к странице учетной записи</div>");
});
}
Если вам понравилась данная статья, рекомендую к прочтению:
1) пошаговое руководство по созданию простого REST API в php (часть 1).
2) jQuery + AJAX + JSON + PHP (часть 2).
Надеюсь, вам понравилась данная информация. Если вам интересна тема web-разработки, то можете следить за выходом новых статей в Telegram.
Поделиться с друзьями:
Статьи из данной категории:
Комментарии (11)
- Васисулий
- Александр
- Выщипанная Обезьяна
- Павел
- Роман
- Светлана
- Даня
- ytka
- Борис
- Дед Митяй
- Владимир