1. Обзор
В предыдущих статьях мы рассмотрели основы JHipster и способы его использования для создания приложения на основе микросервисов .
В этом руководстве мы рассмотрим службу учетных записей пользователей и авторизации JHipster — для краткости UAA — и как ее использовать для защиты полноценного микросервисного приложения на основе JHispter. Более того, всего этого можно добиться, не написав ни единой строчки кода !
2. Основные функции UAA
Важной особенностью приложений, которые мы создали в наших предыдущих статьях, является то, что учетные записи пользователей были их неотъемлемой частью. Теперь это нормально, когда у нас есть одно приложение, но что, если мы хотим разделить учетные записи пользователей между несколькими приложениями, созданными JHipster? Вот тут-то и появляется UAA JHipster.
UAA JHipster — это микросервис, который создается , развертывается и запускается независимо от других сервисов в нашем приложении . Он служит:
- Сервер авторизации OAuth2, основанный на реализации Spring Boot.
- Сервер управления идентификацией, предоставляющий CRUD API учетной записи пользователя.
JHipster UAA также поддерживает типичные функции входа в систему, такие как самостоятельная регистрация и «запомнить меня». И, конечно же, он полностью интегрируется с другими сервисами JHipster.
3. Настройка среды разработки
Прежде чем начинать какую-либо разработку, мы должны сначала убедиться, что в нашей среде настроены все предпосылки. Помимо всех инструментов, описанных в нашей статье «Введение в JHipster», нам понадобится работающий реестр JHipster. Напомню, что служба реестра позволяет различным службам, которые мы создадим, находить друг друга и взаимодействовать друг с другом.
Полная процедура создания и запуска реестра описана в разделе 4.1 нашей статьи JHipster с микросервисной архитектурой , поэтому мы не будем повторять ее здесь. Также доступен образ Docker, который можно использовать в качестве альтернативы.
4. Создание нового сервиса JHipster UAA
Давайте создадим наш сервис UAA с помощью утилиты командной строки JHipster:
$ mkdir uaa
$ cd uaa
$ jhipster
Первый вопрос, на который мы должны ответить, — это тип приложения, которое мы хотим создать. Используя клавиши со стрелками, мы выберем опцию «JHipster UAA (для аутентификации микросервиса OAuth2)»:
Далее нам будет предложено задать несколько вопросов, касающихся конкретных сведений о созданной службе, таких как имя приложения, порт сервера и обнаружение службы:
По большей части ответы по умолчанию подходят. Что касается базового имени приложения, которое влияет на многие генерируемые артефакты , мы выбрали «uaa»
(нижний регистр) — разумное имя. Мы можем поиграть с другими значениями, если захотим, но это не изменит основных характеристик сгенерированного проекта.
Ответив на эти вопросы, JHipster создаст все файлы проекта и установит зависимости пакетов npm
(которые в данном случае на самом деле не используются).
Теперь мы можем использовать локальный скрипт Maven для создания и запуска нашего сервиса UAA:
$ ./mvnw
... build messages omitted
2018-10-14 14:07:17.995 INFO 18052 --- [ restartedMain] com.foreach.jhipster.uaa.UaaApp :
----------------------------------------------------------
Application 'uaa' is running! Access URLs:
Local: http://localhost:9999/
External: http://192.168.99.1:9999/
Profile(s): [dev, swagger]
----------------------------------------------------------
2018-10-14 14:07:18.000 INFO 18052 --- [ restartedMain] com.foreach.jhipster.uaa.UaaApp :
----------------------------------------------------------
Config Server: Connected to the JHipster Registry config server!
----------------------------------------------------------
Ключевым сообщением, на которое следует обратить внимание, является сообщение о том, что UAA подключен к реестру JHipster. Это сообщение указывает на то, что UAA смог зарегистрироваться и будет доступен для обнаружения другими микросервисами и шлюзами.
5. Тестирование службы UAA
Поскольку сгенерированный сервис UAA сам по себе не имеет пользовательского интерфейса, мы должны использовать прямые вызовы API, чтобы проверить, работает ли он должным образом.
Есть две функции, которые мы должны убедиться, что они работают, прежде чем использовать его с другими частями или нашей системой: создание токена OAuth2 и получение учетной записи.
Во-первых, давайте получим новый токен из конечной точки OAuth нашего UAA , используя простую команду curl
:
$ curl -X POST --data \
"username=user&password=user&grant_type=password&scope=openid" \
http://web_app:changeit@localhost:9999/oauth/token
Здесь мы использовали поток предоставления пароля , используя две пары учетных данных.
В этом виде потока мы отправляем учетные данные клиента, используя базовую HTTP-аутентификацию, которую мы кодируем непосредственно в URL-адресе.
Учетные данные конечного пользователя отправляются как часть тела с использованием стандартных параметров имени пользователя и пароля. Мы также используем учетную запись пользователя с именем «user»
, которая доступна по умолчанию в тестовом профиле.
Предполагая, что мы предоставили все данные правильно, мы получим ответ, содержащий токен доступа и токен обновления:
{
"access_token" : "eyJh...(token omitted)",
"token_type" : "bearer",
"refresh_token" : "eyJ...(token omitted)",
"expires_in" : 299,
"scope" : "openid",
"iat" : 1539650162,
"jti" : "8066ab12-6e5e-4330-82d5-f51df16cd70f"
}
Теперь мы можем использовать возвращенный access_token
для получения информации для связанной учетной записи с помощью ресурса учетной записи
, который доступен в сервисе UAA:
$ curl -H "Authorization: Bearer eyJh...(access token omitted)" \
http://localhost:9999/api/account
{
"id" : 4,
"login" : "user",
"firstName" : "User",
"lastName" : "User",
"email" : "user@localhost",
"imageUrl" : "",
"activated" : true,
"langKey" : "en",
"createdBy" : "system",
"createdDate" : "2018-10-14T17:07:01.336Z",
"lastModifiedBy" : "system",
"lastModifiedDate" : null,
"authorities" : [ "ROLE_USER" ]
}
Обратите внимание, что мы должны выполнить эту команду до истечения срока действия маркера доступа . По умолчанию служба UAA выдает токены, действительные в течение пяти минут, что является разумным значением для производства.
Мы можем легко изменить срок службы действительных токенов, отредактировав файл application-<profile>.yml
, соответствующий профилю, под которым мы запускаем приложение, и установив uaa.web-client-configuration.access-token-validity-in-
клавиша секунд .
Файлы настроек находятся в каталоге src/main/resources/config
нашего проекта UAA.
6. Создание шлюза с поддержкой UAA
Теперь, когда мы уверены, что наша служба UAA и реестр служб работают, давайте создадим экосистему для их взаимодействия. В конце мы добавим:
- Интерфейс на основе Angular
- Серверная часть микросервиса
- Шлюз API, который выходит на оба этих
Давайте начнем со шлюза, так как это будет служба, которая будет согласовывать аутентификацию с UAA. Он будет размещать наше внешнее приложение и направлять запросы API к другим микросервисам.
Еще раз, мы будем использовать инструмент командной строки JHipster внутри только что созданного каталога:
$ mkdir gateway
$ cd gateway
$ jhipster
Как и прежде, мы должны ответить на несколько вопросов, чтобы сгенерировать проект. Важными являются следующие:
Тип приложения
: должен быть «Шлюз микросервисов» .Имя приложения:
на этот раз мы будем использовать «шлюз» .Обнаружение службы
: выберите «Реестр JHipster».Тип аутентификации:
мы должны выбрать здесь опцию «Аутентификация с сервером JHipster UAA».UI Framework:
давайте выберем «Angular 6»
Как только JHipster сгенерирует все свои артефакты, мы можем создать и запустить шлюз с предоставленным сценарием-оболочкой Maven:
$ ./mwnw
... many messages omitted
----------------------------------------------------------
Application 'gateway' is running! Access URLs:
Local: http://localhost:8080/
External: http://192.168.99.1:8080/
Profile(s): [dev, swagger]
----------------------------------------------------------
2018-10-15 23:46:43.011 INFO 21668 --- [ restartedMain] c.foreach.jhipster.gateway.GatewayApp :
----------------------------------------------------------
Config Server: Connected to the JHipster Registry config server!
----------------------------------------------------------
С помощью приведенного выше сообщения мы можем получить доступ к нашему приложению, указав в браузере адрес http://localhost:8080 ,
который должен отображать сгенерированную по умолчанию домашнюю страницу:
Давайте продолжим и войдем в наше приложение, перейдя в пункт меню « Учетная запись»> «Войти» .
Мы будем использовать admin/admin
в качестве учетных данных, которые JHipster создает автоматически по умолчанию. Все идет хорошо, на странице приветствия отобразится сообщение, подтверждающее успешный вход в систему:
Давайте вспомним, что привело нас к этому: во-первых, шлюз отправил наши учетные данные на конечную точку токена OAuth2 UAA, которая проверила их и сгенерировала ответ, содержащий токен JWT для доступа и обновления. Затем шлюз взял эти токены и отправил их обратно в браузер в виде файлов cookie.
Затем внешний интерфейс Angular вызвал API /uaa/api/account
, который шлюз снова перенаправил в UAA. В этом процессе шлюз берет файл cookie, содержащий токен доступа, и использует его значение для добавления заголовка авторизации к запросу.
При необходимости мы можем увидеть весь этот поток в мельчайших деталях, проверив журналы UAA и Gateway. Мы также можем получить полные данные на уровне проводов, установив уровень регистратора org.apache.http.wire
на DEBUG.
7. Создание микросервиса с поддержкой UAA
Теперь, когда среда нашего приложения настроена и работает, пришло время добавить в нее простую микрослужбу. Мы создадим микросервис «quotes», который предоставит полный REST API, который позволит нам создавать, запрашивать, изменять и удалять набор котировок акций. Каждая цитата будет иметь только три свойства:
- Торговый символ котировки
- Его цена и
- Отметка времени последней сделки
Вернемся к нашему терминалу и воспользуемся инструментом командной строки JHipster для создания нашего проекта:
$ mkdir quotes
$ cd quotes
$ jhipster
На этот раз мы попросим JHipster сгенерировать приложение Microservice
, которое назовем «кавычки». Вопросы аналогичны тем, на которые мы уже отвечали. Мы можем оставить значения по умолчанию для большинства из них, кроме этих трех:
Обнаружение службы:
выберите «Реестр JHipster», так как мы уже используем его в нашей архитектуре .Путь к приложению UAA:
поскольку мы храним все каталоги проектов в одной папке, это будет../uaa
(если мы его не изменили, конечно)Тип аутентификации:
выберите «Сервер JHipster UAA».
Вот как будет выглядеть типичная последовательность ответов в нашем случае:
Как только JHipster завершит создание проекта, мы можем продолжить его сборку:
$ mvnw
... many, many messages omitted
----------------------------------------------------------
Application 'quotes' is running! Access URLs:
Local: http://localhost:8081/
External: http://192.168.99.1:8081/
Profile(s): [dev, swagger]
----------------------------------------------------------
2018-10-19 00:16:05.581 INFO 16092 --- [ restartedMain] com.foreach.jhipster.quotes.QuotesApp :
----------------------------------------------------------
Config Server: Connected to the JHipster Registry config server!
----------------------------------------------------------
... more messages omitted
Сообщение «Подключено к серверу конфигурации JHipster Registry!» это то, что мы ищем здесь. Его наличие говорит нам о том, что микросервис зарегистрировался в реестре, и поэтому шлюз сможет направлять запросы к нашему ресурсу «кавычки» и отображать его в удобном пользовательском интерфейсе после того, как мы его создадим. Поскольку мы используем микросервисную архитектуру, мы разделили эту задачу на две части:
- Создайте серверную службу ресурса «quotes»
- Создайте пользовательский интерфейс «кавычки» во внешнем интерфейсе (часть проекта шлюза)
7.1. Добавление ресурса Quotes
Во- первых, нам нужно убедиться, что приложение микросервиса кавычек остановлено — мы можем нажать CTRL-C в том же окне консоли, которое мы ранее использовали для его запуска.
Теперь давайте добавим объект в проект с помощью инструмента JHipster. На этот раз мы воспользуемся командой import-jdl
, которая избавит нас от утомительного и подверженного ошибкам процесса предоставления всех деталей по отдельности. Дополнительные сведения о формате JDL см. в полном справочнике по JDL .
Затем мы создаем текстовый файл с именем quotes.jh
, содержащий определение сущности Quote
вместе с некоторыми директивами генерации кода:
entity Quote {
symbol String required unique,
price BigDecimal required,
lastTrade ZonedDateTime required
}
dto Quote with mapstruct
paginate Quote with pagination
service Quote with serviceImpl
microservice Quote with quotes
filter Quote
clientRootFolder Quote with quotes
Теперь мы можем импортировать это определение объекта в наш проект:
$ jhipster import-jdl quotes.jh
Примечание: во время импорта JHipster будет жаловаться на конфликт при внесении изменений в файл master.xml
. В этом случае мы можем безопасно выбрать вариант перезаписи .
Теперь мы можем снова собрать и запустить наш микросервис, используя mvnw.
Как только он будет запущен, мы можем убедиться, что шлюз выбирает новый маршрут, получая доступ к представлению шлюза
, доступному в меню « Администрирование ».
На этот раз мы видим запись для маршрута «/quotes/**»
`` , которая показывает, что серверная часть готова к использованию пользовательским интерфейсом.
7.2. Добавление пользовательского интерфейса котировок
Наконец, давайте сгенерируем пользовательский интерфейс CRUD в проекте шлюза, который мы будем использовать для доступа к нашим котировкам. Мы будем использовать тот же файл JDL из проекта микросервиса «quotes» для создания компонентов пользовательского интерфейса и импортируем его с помощью команды JHipster import-jdl
:
$ jhipster import-jdl ../jhipster-quotes/quotes.jh
...messages omitted
? Overwrite webpack\webpack.dev.js? <b>y</b>
... messages omitted
Congratulations, JHipster execution is complete!
Во время импорта JHipster несколько раз предложит действие, которое следует предпринять в отношении конфликтующих файлов. В нашем случае мы можем просто перезаписать существующие ресурсы, так как мы не делали никаких настроек.
Теперь мы можем перезапустить шлюз и посмотреть, чего мы достигли. Давайте направим наш браузер на шлюз по адресу http://localhost:8080
, убедившись, что мы обновляем его содержимое. В меню Entities
теперь должна быть новая запись для ресурса Quotes :
При нажатии на этот пункт меню открывается экран со списком котировок :
Как и ожидалось, листинг пуст — мы еще не добавили ни одной цитаты! Давайте попробуем добавить один, нажав кнопку «Создать новую цитату» в правом верхнем углу этого экрана, что приведет нас к форме создания/редактирования:
Мы видим, что сгенерированная форма имеет все ожидаемые функции:
- Обязательные поля отмечены красным индикатором, который после заполнения становится зеленым.
- Дата/время и числовые поля используют собственные компоненты для упрощения ввода данных.
- Мы можем отменить это действие, что оставит данные без изменений, или сохранить нашу новую или измененную сущность.
После заполнения этой формы и нажатия кнопки « Сохранить»
мы увидим результаты на экране со списком. Теперь мы можем увидеть новый экземпляр Quotes
`` в сетке данных:
В качестве администратора у нас также есть доступ к пункту меню API , который ведет нас на стандартный портал разработчиков Swagger API. На этом экране мы можем выбрать один из доступных API для тренировки:
по умолчанию:
собственный API шлюза, отображающий доступные маршрутыuaa
: API учетной записи и пользователякотировки:
API котировок
8. Следующие шаги
Приложение, которое мы создали, работает так, как ожидалось, и обеспечивает прочную основу для дальнейшей разработки. Нам определенно нужно будет написать немного (или много) пользовательского кода, в зависимости от сложности наших требований. Некоторые области, которые, вероятно, потребуют некоторой работы:
Настройка внешнего вида пользовательского интерфейса:
обычно это довольно просто из-за того, как структурировано интерфейсное приложение — мы можем пройти долгий путь, просто повозившись с CSS и добавив несколько изображений.Изменения репозитория пользователей:
в некоторых организациях уже есть какой-то внутренний репозиторий пользователей (например, каталог LDAP) — для этого потребуются изменения в UAA, но приятно то, что нам нужно изменить его только один раз.Более детальная авторизация сущностей:
стандартная модель безопасности, используемая серверной частью сгенерированной сущности, не имеет какой-либо защиты на уровне экземпляра и/или на уровне поля — разработчик должен добавить эти ограничения на соответствующий уровень (API). или услуги, в зависимости от случая)
Даже с учетом этих замечаний использование такого инструмента, как JHispter, может сильно помочь при разработке нового приложения. Это принесет с собой прочную основу и может поддерживать хороший уровень согласованности в нашей кодовой базе по мере развития системы и разработчиков.
9. Заключение
В этой статье мы показали, как использовать JHispter для создания работающего приложения на основе архитектуры микросервисов и сервера JHipster UAA. Мы добились этого, не написав ни одной строчки Java-кода , что весьма впечатляет.
Как обычно, полный код проектов, представленных в этой статье, доступен в нашем репозитории GitHub .