Используйте сервис аутентификации для проверки токена JWT и защиты других ваших микросервисов (Lab01 — часть 2)

Где мы остановились

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

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

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

Наконец, я покажу, как я подключил все микросервисы с помощью docker-compose.

Вы можете найти проект Github здесь.

Статьи организованы следующим образом:

Часть 1:

  • Большая картина
  • Служба аутентификации

Часть 2:

  • Служба дел
  • Запустите все сервисы с помощью docker-compose

Следуйте за мной, и давайте погрузимся в эту заключительную часть!

Служба дел

Как показано в приведенном выше скетче, мы хотим использовать службу аутентификации, чтобы сообщить нам, авторизован ли текущий пользователь (200) для использования службы дел или нет (401).

Для этого мы хотим, чтобы каждый запрос отправлялся с полем Authorization в заголовке с токеном носителя, сгенерированным службой аутентификации. В противном случае запрос будет отклонен с кодом состояния 401.

Сервис был реализован с помощью Flask, веб-фреймворка, написанного на Python, который позволяет легко разрабатывать веб-приложения.

Давайте посмотрим на структуру проекта.

Как и в случае со службой авторизации, я создал bash-скрипты и Makefile для автоматизации утомительных процессов.
Вы также можете использовать их, чтобы ускорить весь процесс и быть готовым к игре.

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

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

В моем случае я использую БД SQLite в среде разработки и переключаюсь на БД PostgreSQL в рабочем режиме с докером.

Файл python runner.py будет запущен, когда вы запустите приложение с помощью команды flask run (она будет проверять, какой файл выполняется на основе параметра FLASK_APP) или python runner.py .

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

Исходная папка

Давайте посмотрим, что находится внутри папки src. Здесь есть основная логика и взаимодействия, которые описывают наш сервис to-do.

app.py — Содержит все конфигурации, все расширения и все маршруты, зарегистрированные внутри приложения.

Несмотря на все другие примеры app.py, которые вы можете найти, я думаю, что эта структура более гибкая и организованная. У всего есть свое место, будь то расширение или новый маршрут.

Как вы увидите, тот же подход заключается в том, чтобы отделить основные действия (службы) от определения маршрутов (схемы). Это позволяет мне сохранять все маршруты небольшими, чистыми и удобными в сопровождении.

Если вам интересно, я подробно покажу вам, как я обычно структурирую свой проект flask, дайте мне знать в разделе комментариев.

extensions.py

В этом файле я храню все необходимые расширения, которые мне нужны в моем приложении фляги. Таким образом, я могу легко импортировать БД в свои чертежи или служебные файлы, например, без использования файла app.py. Я считаю, что это проще и понятнее.

config.py

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

Как мы видим, когда мы запускаем приложение в среде разработки, будет сгенерирован локальный todo.db. То же самое для тестирования. Другая ситуация возникает, когда приложение будет работать в производственной среде (в данном случае в нашем контейнере Docker), где будет установлено соединение с базой данных PostgreSQL.

decorators.py

В файле decorators.py происходит волшебство!

Что касается службы авторизации, каждый запрос будет защищен с помощью декоратора @is_authorized, который будет выполняться перед текущим запросом. Он проверит, есть ли поле Authorization в запросе заголовка.

Если это так, класс Auth, взаимодействующий со службой аутентификации, проверит, что пользователь авторизован на основе переданного токена носителя. В противном случае будет возвращен код состояния 401, и никакие действия не будут выполнены.

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

curl --location --request GET 'http://localhost:5000/api/v1/todo/?completed=false'
# curl GET 'http://localhost:5000/api/v1/todo/?completed=false' \                     
--header 'Authorization: Bearer mynotvalidtoken'
<!doctype html>
<html lang=en>
<title>401 Unauthorized</title>
<h1>Unauthorized</h1>
<p>The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn&#x27;t understand how to supply the credentials required.</p>

Итак, давайте посмотрим, как выглядит класс Auth внутри service/auth_service.py.

Класс Auth оборачивает необходимые API-интерфейсы, доступные в службе аутентификации, для проверки переданного токена и возвращает user_id пользователя, который отправляет запрос.

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

def __init__(self):                                         self.AUTH_SERVICE_NAME = os.getenv('AUTH_SERVICE_NAME', 'localhost')                                     self.AUTH_SERVICE_PORT = os.getenv('AUTH_SERVICE_PORT', '8000')

Метод get_user() позволяет нам получить user_id на основе токена носителя внутри запроса. user_id будет использоваться в качестве поля в нашей модели для сопоставления пользователя и его задач.

blueprints/todo.py

Здесь мы можем найти все возможные взаимодействия, которые мы можем сделать с сервисом to-do:

  • Получите все задачи пользователя, в конечном итоге отфильтрованные по полному статусу
  • Создать новую задачу
  • Ставить задачу как выполненную
  • Обновить новый текст задачи
  • Удалить задачу

Все маршруты защищены декоратором @is_authorized, и для каждого запроса текущий пользователь извлекается перед выполнением какого-либо действия.

Файл Docker

Docker может создавать образы автоматически, читая инструкции из файла Dockerfile. Dockerfile – это текстовый документ, содержащий все команды, которые пользователь может вызвать в командной строке для сборки изображения. С помощью docker build пользователи могут создать автоматизированную сборку, которая последовательно выполняет несколько инструкций командной строки.

Вот как я определил Dockerfile:

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

Когда вы запускаете контейнер Docker, он проверяет, установлено ли соединение с БД PostgreSQL, прежде чем переходить к другим инструкциям.

Затем базовый образ будет использоваться для создания образа dev. Когда контейнер запустится, будет выполнена команда python runner.py, а приложение flask запустится под 0.0.0.0:5000.

Запуск службы

Пришло время запустить сервис! Я подготовил Makefile, чтобы автоматизировать скучные вещи. Если вы загрузили код, вы можете просто ввести команду make <target> и наслаждаться!

docker-build: будет создан образ докера с именем msalab01/todo:v1.

docker-run: он запустит док-контейнер с именем lab01_todo. Если вам нужно использовать другой порт, вы должны указать в команде make переменную PORT, иначе будет использоваться 5000.

local-build: Он запустит bootstrap.sh, который автоматизирует все начальные настройки, такие как создание виртуальной среды и установка зависимостей.

local-run: будет запущен start_local_server.sh,скрипт bash, который выполняет все основные инструкции для локального запуска сервера.

Примечание. Если вы решите запускать службы с помощью контейнера докеров независимо друг от друга, вы не сможете установить связь между службами, если только не поместите их в одну сеть. Мое предложение, если вы хотите протестировать их, прежде чем перемещаться внутри docker-compose, — запускать оба локально.

Запустите все сервисы с помощью docker-compose

Наконец, пришло время собрать все воедино!

Чтобы запустить все сервисы вместе и позволить им взаимодействовать друг с другом, нам нужно записать файл docker-compose.

Docker Compose — это инструмент, разработанный для помощи в определении и совместном использовании мультиконтейнерных приложений. С помощью Compose мы можем создать файл YAML для определения служб и с помощью одной команды можем все развернуть или разорвать.

Давайте посмотрим, как выглядит наш файл.

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

служба аутентификации: она получает ранее созданный образ mslab01/auth:v1. Кроме того, поскольку мы используем БД PostgreSQL, мы устанавливаем POSTGRES_ENABLED=1, и соединение между БД будет установлено путем передачи тех же атрибутов, которые использовались для создания auth_db. Это возможно, потому что auth и auth_db используют одну и ту же сеть backend_auth_db. Кроме того, чтобы разрешить связь с интерфейсной службой, нам также необходимо поместить службу в сеть frontend.

Служба задач: получает образ mslab01/todo:v1, созданный ранее. Та же история и с этим сервисом, и с его базой данных (todo_db). Кроме того, мы передали AUTH_SERVICE_NAME и AUTH_SERVICE_PORT службы аутентификации, чтобы разрешить внутреннюю связь между контейнерами через порты контейнера. В этом случае службы аутентификации и todo используют одну и ту же интерфейсную сеть.

веб-приложение: используется веб-приложение, созданное в Vue3. Я не буду показывать, как он был создан, потому что это выходит за рамки, если вам интересно, вы можете увидеть код на Github. Вы можете выбрать предпочитаемый фреймворк и вызывать API с помощью Axios, Fetch или Ajax.

Готов идти!

Время, которого мы ждали, наконец, пришло.

Чтобы запустить службу, в вашем терминале под корневым проектом (или там, где вы создаете свой окончательный docker-compose.yml) введите команду:

docker-compose up -d

Перейдите на localhost или localhost:80, создайте новую учетную запись, если вы еще этого не сделали, и наслаждайтесь успехом!

Заключение

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

Я рад, что поделился с вами этим экспериментом, и надеюсь, вы нашли его полезным для своего следующего проекта!

Надеюсь увидеть вас на следующем семинаре!
Подпишитесь на меня, чтобы ничего не пропустить.

До встречи!

Полезные ссылки



«Как защитить ваши микросервисы (1/2)
Используйте службу аутентификации для проверки токена JWT и защиты других ваших микросервисов (lab01 — часть 1)лучшее программирование. паб"