DropTrigger

DropTrigger

Вкатываюсь в IT
На Пикабу
99 рейтинг 11 подписчиков 0 подписок 15 постов 0 в горячем
3

Создаю онлайн-сервис для чтения книг. День 6-9. CRUD, Дизайн+Верстка, Frontend(JWT)

Серия Записки вкатуна

Термины в статье:

  1. Эндпоинт

  2. Аутентификация, Регистрация, JWT, Access, Refresh

К стеку добавился:

  • Vue.js


Дописываю API

Потратив 2 ночи (и немного терпения), я наконец завершил реализацию всех эндпоинтов! В какой-то момент это очень наскучило, но я все равно продолжал писать их.

Как выглядят эндпоинты в этой статье - Создаю онлайн-сервис для чтения книг. День 4. Обработка первого запроса.

Архитектура папок теперь выглядит вот так:

Всего реализовано 38 эндпоинтов , и это еще не конец — их количество будет расти! Последний из них ощущался как будто я пробежал марафон.


Разработка дизайна 🎨

Но как делать веб без дизайна? Верно, никак! 🤔
Зайдя в Figma и подсмотрев интерфейс GitHub'а , я накидал ориентировочный дизайн страниц регистрации и входа.


Верстка 🖥️

Верстка — это немного рутинное занятие, но результат того стоит!
Могу сказать, что получилось почти идентично дизайну.


Frontend с Vue.js

Почему Vue.js ? Просто такие условия 🙃. Если бы выбор был за мной, я бы взял React .

Добавлю в решение новый проект Веб-приложение ASP.NET Core (MVC) . Стандартный шаблон создаст такие папки:

  • wwwroot
    Это корневая папка для статических файлов, которые будут доступны напрямую через браузер.

  • Controllers
    Папка содержит классы контроллеров, которые управляют маршрутизацией.

  • Models
    Папка содержит модели данных, которые представляют сущности приложения.

  • Views
    Папка содержит представления — файлы, которые отвечают за отображение HTML-страниц пользователю.

В папку wwwroot/lib добавлю клиентскую библиотеку Vue.js .

Создам новый контроллер для страниц аутентификации.

В папке Views есть еще 2 папки:

  • Home

  • Shared

В папку Shared добавлю новый шаблон страницы Razor с названием _LoginLayout для страниц аутентификации.

Создам папку Auth, добавив туда пустую страницу Razor с названием _ViewStart. Этот файл указывает какой шаблон будут использовать страницы.

@{

Layout = "_LoginLayout";

}

Теперь закину в wwwroot/css свой файл со стилем, который наверстал.


Логика фронтенда 🧠

Начну со страницы входа, добавив HTML-разметку, которую наверстал.

Снизу файла напишу блок скриптов:

@Section scripts {

<script src="~/lib/vue/vue.global.js"></script>

<script>

...тут будут все скрипты...

</script>

}

Пример запроса на бэкенд:

На скрине показан метод ассинхронный метод login(), в нем реализована отправка запроса на эндпоинт /auth/login, если запрос проходит успешно, я записываю Access-токен в локальное хранилище и перенаправляю пользователя на страницу по адресу /home. В противном случае я показываю ошибку пользователю.

В ответе сервера я получаю Access и Refresh токены.

  • Access-токен записываю в локальное хранилище.

  • Refresh-токен храню в Http-only куках для большей безопасности 🛡️.

Пример записи куки на сервере:

Здесь я записал новую куку с под названием refreshToken, и значением, равным Refresh-токену.

Вообще для чего мне Refresh-токен, если есть Access? Все очень просто, у Access-токена срок жизни 15 минут, поэтому через 15 минут его необходимо будет сгенерировать заново. Для этого как раз и понадобится Refresh-токен.

По истечению Access-токена я буду посылать на сервер запрос со своими куками. Сервер прочитает Refresh-токен из них и, если он валидный, вернет новый Access-токен.

Как это реализовано со стороны сервера:

Со стороны клиента:

При загрузке страницы сразу же срабатывает метод checkRefreshToken, далее отправляется запрос на /auth/refresh. Если сервер возвращает положительный ответ, записываю новый Access в локальное хранилище и продолжаю пользоваться сервисом.

Тестирование 🧪

Запущу бэкенд и фронтенд.

После запуска я сразу попадаю на страницу входа.

Войду в аккаунт, который я создвал еще на начальных этапах.

Если сейчас обратиться по адресу /home, меня перекинет назад на страницу авторизации.

Попробую сначала ввести неправильный пароль.

Теперь введу правильный пароль. Все сработало! Я попал на домашнюю страницу.

Зайдя в консоль разработчика, можно посмотреть локальное хранилище и найти там Access-токен.

Теперь я могу пользоваться сервисом, отправляя запросы на эндпоинты, передавая данный токен в заголовке.

Показать полностью 15
2

Создаю онлайн-сервис для чтения книг. День 5. Подтверждение почты

Серия Записки вкатуна

🎁 Бонусная статья.


🛠️ Добавлю новую таблицу в БД

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

  • id: уникальный идентификатор

  • code: сгенерированный код

  • email: почта, на которую пришел код

  • expires_in: дата и время истечения кода


🖥️ Создам интерфейс и реализую его

Опишу методы работы с этой базой данных через интерфейс.


🔐 Интерфейс сервиса аутентификации

В интерфейс добавлю логику для отправки кода на почту.

Отправляться будет шестизначный код. Генерация кода выглядит так:


📧 Настройка почты

Теперь зайду в mail.ru и создам новую почту. Перейду в настройки безопасности и выберу пункт "Пароли для внешних приложений" . Создам новое внешнее приложение и получу для него пароль. Запишу его себе куда-нибудь.


📦 Подключаю библиотеку System.Net.Mail

Для отправки сообщений необходимо подключить библиотеку System.Net.Mail. Она поможет настроить SMTP-клиент и отправить письмо.


🎯 Генерация кода и запись в БД

1. Параметры SMTP-сервера

Эти переменные необходимы для настройки подключения к SMTP-серверу, который будет отправлять письмо.

smtpServer

smtpPort

  • Описание : Порт, используемый для подключения к SMTP-серверу. Обычно это:

    • 587 (для TLS/STARTTLS)

    • 465 (для SSL)

  • Пример : 587 для Gmail или Mail.ru.

smtpUsername

  • Описание : Логин (обычно email), который используется для аутентификации на SMTP-сервере.

smtpPassword

  • Описание : Пароль для аутентификации на SMTP-сервере. В моем случае я вписал пароль, который недавно получил от mail.ru.


2. Параметры объекта MailMessage

Класс MailMessage используется для создания самого письма. Вот его основные параметры:

IsBodyHtml = true

  • Описание : Этот флаг указывает, что тело письма содержит HTML-разметку. Если установлено значение false, то тело письма будет обрабатываться как простой текст.

From

  • Описание : Указывает адрес отправителя. Это поле должно быть заполнено объектом типа MailAddress.

To

  • Описание : Указывает адрес получателя. Можно добавить несколько адресов с помощью метода message.To.Add().

Subject

  • Описание : Тема письма, которая отображается в заголовке сообщения.

Body

  • Описание : Тело письма. Если IsBodyHtml = true, то здесь можно использовать HTML-разметку. В противном случае это будет простой текст. В моем случае я сверстал небольшую форму, записал её в отдельную переменную класса Constaints.


🌐 Добавляю эндпоинт

Создам эндпоинт, который будет отвечать за отправку сообщения. Например:


🧪 Тестирую!

Запускаю сервер и тестирую функционал:

  • Ввожу адрес электронной почты, на который хочу отправить сообщение. 📝

  • Нажимаю "Выполнить". ✅

И... Письмо пришло! 🎉


🗄️ Проверяю БД

Убеждаюсь, что запись добавлена в базу данных. Все отлично работает! ✅

🎉 Итог

Теперь пользователи могут подтвердить свою почту с помощью шестизначного кода.

Показать полностью 9
1

Создаю онлайн-сервис для чтения книг. День 5. JWT, Refresh, Access

Серия Записки вкатуна

Термины в статье:

  1. CRUD, крудошлеп

  2. Endpoint

  3. JWT

🚀 Изменения в БД:

Для поддержки доступа к сайту с нескольких устройств (веб, десктоп, мобильное приложение) в таблицу UserSessions были добавлены следующие столбцы:

  • device_type : Тип устройства (web, desktop, mobile)

  • created_at : Дата создания сессии


🛠️ Изменения в коде:

1. Удаление флага bool Flag

Ранее в ответах сервера использовался флаг bool Flag для обозначения успешности операции. Теперь обработка ошибок выполняется через блоки try-catch. Это делает код более читаемым и устойчивым к ошибкам.


🐣 Реализация JWT-токенов

  1. В файл конфигурации appsettings.json добавлен новый раздел JwtSection, содержащий секретный ключ и время жизни токена:

  2. Для удобства работы с JWT был создан вспомогательный класс, который хранит данные из раздела JwtSection.

  3. В Program.cs этот класс подключается следующим образом:

    builder.Services.Configure<JwtSection>(builder.Configuration.GetSection("JwtSection"));

  4. Был создан интерфейс, описывающий логику работы с базой данных для управления сессиями.

  5. Реализую данный интерфейс. 💻


🔑 Генерация токенов:

Для генерации refresh-токена используется метод, который создает случайную строку из 32 байт:

Для генерации access-токена необходимы данные о пользователе (claims), секретный ключ из appsettings.json и срок действия токена:


🔒 Метод SignIn:

В методе SignIn происходит следующее:

  1. Генерируются Access и Refresh токены.

  2. Проверяется наличие сессии в базе данных. Если сессия существует, обновляется Refresh-токен.

  3. Если сессия не найдена, создается новая запись в таблице UserSessions.


Обновление токенов 🔄

Если срок действия Access-токена истек, пользователь может получить новый токен, используя Refresh-токен. Для этого реализован метод RefreshToken:

Здесь происходят базовые проверки, во избежание ошибок. Далее генерируется новый Access-токен. Если срок Refresh-токена истек, то генерирую новый и отправляю его пользователю вместе с Access-токеном.


Защита эндпоинтов 🛡️

Для защиты эндпоинтов от неавторизованных пользователей была добавлена логика обработки Access-токенов:

Здесь из appsettings.json достаются все данные из ячейки JwtSection и помещаются в переменную config. Это позволяет централизованно управлять секретным ключом и временем жизни токена.

Далее добавляется аутентификация, указывая схему аутентификации (JwtBearer) в качестве параметра. Для этого используется метод AddJwtBearer, который как раз и будет валидировать токен. В нем указываются следующие проверки:

  • Срок жизни токена : Убедиться, что токен не истек. ⏳

  • Ключ шифрования : Проверить, что токен был подписан с использованием корректного секретного ключа. 🔑

В Program.cs регистрируется метод AddAuth:

builder.Services.AddAuth(builder.Configuration);

Также добавлены строки для использования аутентификации и авторизации

app.UseAuthentication();

app.UseAuthorization();

Теперь необходимо защитить Endpoint. Защищенные эндпоинты помечаются атрибутом [Authorize]:


Проверка работоспособности ▶️

Регистрация нового аккаунта 🆕

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


Авторизация 🔑

После входа в систему пользователь получает Access и Refresh токены.


Проверка токена на jwt.io 🔍

На сайте jwt.io можно проверить содержимое Access-токена. В поле Payload видны все Claims.


Обращение к защищенному эндпоинту без токена 🚫

Получен статус-код 401, что означает "Доступ запрещен".


Обращение с токеном ✅

После добавления токена в заголовок Authorization запрос выполнен успешно (статус-код 200).


Заключение 🎉

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

🥁 А темой для следующей статьи станет:

Подтверждение почты через отправку кода в письме

Показать полностью 17
1

Термины вкатуна. CRUD, крудошлеп

Серия Термины вкатура
Термины вкатуна. CRUD, крудошлеп

🗄️ Что такое CRUD?

CRUD — это аббревиатура, обозначающая четыре основные операции:

  1. Create (Создание) — добавление новых записей в базу данных.

  2. Read (Чтение) — получение данных из базы.

  3. Update (Обновление) — изменение существующих данных.

  4. Delete (Удаление) — удаление записей.


🤔 Кто такие "крудошлепы"?

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

Показать полностью

Создаю онлайн-сервис для чтения книг. День 4. Обработка первого запроса

Серия Записки вкатуна

Термины в статье:

  1. DTO

  2. Endpoint

  3. JWT

Реализация обработки первого запроса 🚀

1. Добавление логов 📝

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

  • Перейду в проект HelpLibrary и создам новый класс в папке DTOs .

  • Создам DTO для логов:

    DTO Logs

  • Теперь перейду в проект ServerLibrary и добавлю интерфейс ILogRepository для определения класса логов.

  • Реализую этот интерфейс, создав класс LogRepository в папке Implementations . Он содержит:

    • Поле _context, которое объявляется в конструкторе для контекста базы данных.

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

💡 Важно: Такой шаблон будет использоваться для каждой таблицы базы данных.

Qwen2.5-Max1:29 am

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


Реализация обработки первого запроса 🚀

1. Добавление логов 📝

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

  • Перейду в проект HelpLibrary и создам новый класс в папке DTOs .

  • Создам DTO для логов:

  • Теперь перейду в проект ServerLibrary и добавлю интерфейс ILogRepository для определения класса логов.

  • Реализую этот интерфейс, создав класс LogRepository в папке Implementations . Он содержит:

    • Поле _context, которое объявляется в конструкторе для контекста базы данных.

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

💡 Важно: Такой шаблон будет использоваться для каждой таблицы базы данных.


2. Логика работы с пользователями 👤

Создам DTO для регистрации и входа в аккаунт:

  • Для регистрации обязательными полями являются: логин , имя , email и пароль .

  • Для входа в аккаунт необходимы: почта/логин и пароль .

Интерфейс репозитория 🔍

Определяю интерфейс репозитория для работы с базой данных. На данном этапе необходимо реализовать следующие методы:

  • Поиск пользователя по Id .

  • Поиск пользователя по никнейму .

  • Поиск пользователя по email .

  • Добавление пользователя в базу данных.

Реализация интерфейса ⚙️

💼 Реализация бизнес-логики

Создаю интерфейс с методом регистрации и входа в аккаунт.

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

Метод регистрации

Метод входа в аккаунт

3. Контроллер 🌐

Создам новый класс в папке Controllers проекта Server , назову его AuthController . Добавлю в конструктор класса только что созданный сервис.

Добавлю два endpoint'а:

  • POST /register — для регистрации нового пользователя.

  • POST /login — для входа в аккаунт.

📌 Примечание: Swagger автоматически покажет доступные эндпоинты после запуска проекта.

4. Тестирование ✅

Запускаю проект. Открывается страница Swagger, где видны два созданных эндпоинта.

Регистрация 🆕

Открою POST /register и впишу в тело запроса:

{

"nickname": "vkatun",

"name": "vasya",

"email": "vasya@mail.ru",

"password": "password"

}

В итоге получу ответ с сообщением об успешной регистрации и статус-кодом 200!

🎉 Успех! Проверяю базу данных — в таблицах Users и Logs добавились соответствующие записи.

Таблица Users

Таблица Users

Таблица Logs

Таблица Logs

Все работает!

Вход в аккаунт 🔑

Тестирую POST /login с правильными данными:

{

"emailOrNickname": "vkatun",

"password": "password"

}

В итоге получу ответ об успешной аутентификации и статус-кодом 200.

Попробую ввести несуществующий логин и пароль:

{

"emailOrNickname": "vkatun123",

"password": "password"

}

и

{

"emailOrNickname": "vkatun",

"password": "password123"

}

Получу ответы:

{

"flag": false,

"message": "There is no account with this email or nickname."

}

и
{

"flag": false,

"message": "Invalid password"

}

соответственно

⚠️ Ошибка обработана корректно!

5. Заключение 🏁

Все работает корректно! Теперь можно приступить к реализации логики JWT, но это уже тема для другой статьи.

📚 Следите за обновлениями!

Показать полностью 17

Термины вкатуна. Endpoint

Серия Термины вкатура

🤔 Что такое Endpoint?

Endpoint — это конкретный URL-адрес на сервере, который обрабатывает определенный тип запросов от клиента. По сути, это точка входа для взаимодействия с API. Каждый endpoint связан с определенной логикой: получение данных, создание новых записей, обновление или удаление информации.

👀 Примеры endpoints:

  • GET /users — получить список пользователей.

  • POST /users — создать нового пользователя.

  • PUT /users/{id} — обновить данные пользователя с указанным ID.

  • DELETE /users/{id} — удалить пользователя с указанным ID.

🐣 Каждый endpoint имеет:

  1. HTTP-метод : GET, POST, PUT, DELETE и другие.

  2. Путь (URL) : уникальный адрес, который указывает на конкретный ресурс.

  3. Логику обработки : код на сервере, который выполняется при обращении к этому endpoint.

😁 Почему Endpoint Называют "Ручками"?

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

Показать полностью 1
3

Создаю онлайн-сервис для чтения книг. День 2-3. Подключение сервера к БД

Серия Записки вкатуна

👮 Ограничения платформы

Для реализации базовых функций используется .NET 7.0 со следующими компонентами:

  • Avalonia (для кроссплатформенного UI, если потребуется).

  • .NET Framework Core (базовые библиотеки и runtime).

  • .NET Framework Tools (инструменты разработки).

  • .NET Framework Design (шаблоны и архитектурные решения).

🏗️ Проектирование структуры решения
Решение состоит из трёх проектов:

1. Server (Веб-API ASP.NET Core)

  • Роль: Точка входа приложения.

  • Содержит:

    • Эндпоинты API,

    • Middleware,

    • Конфигурацию сервера.

  • Зависимости:

    • ServerLibrary,

    • HelpLibrary,

    • Swashbuckle.AspNetCore.Filters.

2. HelpLibrary (Библиотека классов)

  • Роль: Хранение сущностей БД и DTO.

  • Пример сущности:

    public class User

    {

    public int Id { get; set; }

    public string Name { get; set; }

    }

3. ServerLibrary (Библиотека классов)

  • Роль: Бизнес-логика и работа с БД.

  • Функционал:

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

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

    • Взаимодействие с базой данных.

Структура папок

Структура папок

📦 Установка пакетов Nuget

Для ServerLibrary:

  • Microsoft.AspNetCore.Identity

  • Microsoft.AspNetCore.Authentication.JwtBearer

  • Microsoft.EntityFrameworkCore

  • Microsoft.EntityFrameworkCore.SqlServer

  • Microsoft.EntityFrameworkCore.Tools

  • Microsoft.IdentityModel.Tokens

  • System.IdentityModel.Tokens.Jwt

Для Server:

  • Swashbuckle.AspNetCore.Filters (для документации API).


🔗 НАСТРОЙКА ССЫЛОК МЕЖДУ ПРОЕКТАМИ

  • Проект Server ссылается на:

    • ServerLibrary,

    • HelpLibrary.

Пакеты и ссылки

Пакеты и ссылки

🛠️ Генерация сущностей через scaffolding

Что это такое? - scaffolding

  1. Выполнение команды:

    Scaffold-DbContext "Server=.\SQLEXPRESS;Database=Readify;Trusted_Connection=True;encrypt=false;" Microsoft.EntityFrameworkCore.SqlServer

  2. Распределение кода:

    • DbContext → перемещён в ServerLibrary,

    • Сущности → остаются в HelpLibrary.

В конечном итоге сгенерировались сущности и контекст базы данных.

Контекст базы данных

Контекст базы данных

Сущности

Сущности

🗄️ Настройка подключения к БД

  1. Добавление строки подключения в appsettings.json:

    "ConnectionStrings":

    {

    "DefaultConnection": "Server=.\\SQLEXPRESS;Database=Readify;Trusted_Connection=True;Encrypt=false;"

    }

  2. Регистрация контекста БД в Program.cs:

    builder.Services.AddDbContext<ReadifyContext>(options =>

    {

    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection") ??

    throw new InvalidOperationException("Error to connection!"));

    });


✅ Итоги

  • Сгенерированы сущности БД через EF Core Scaffolding.

  • Настроено подключение к SQL Server.

  • Реализована трёхслойная архитектура:

    • Server (API),

    • HelpLibrary (DTO/Entities),

    • ServerLibrary (Бизнес-логика).

Проект готов к реализации бизнес-логики и разработке API!


Продолжение следует...

Показать полностью 4

Термины вкатуна. Scaffolding

Серия Термины вкатура
Термины вкатуна. Scaffolding

🤔 Что такое scaffolding базы данных?

Scaffolding — это процесс автоматической генерации шаблонного кода на основе структуры БД. Инструменты scaffolding анализируют таблицы, поля, связи и ограничения базы данных, после чего создают готовые компоненты для CRUD-операций (Create, Read, Update, Delete).

Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества