передний план
Мы переходим от монолитной платформы к сервис-ориентированной архитектуре. Мы применяем очень простые принципы DDD и разделяем нашу область на различные ограниченные контексты. Каждый домен распространяется и предоставляет службу через веб-API (REST).
Из-за характера нашего бизнеса у нас есть такие услуги, как бронирование , услуги , клиенты , продукты и т. Д.
Мы также создали Identity Server (на основе Thinktecture Identity Server 3), основная роль которого заключается в следующем:
- Централизованная аутентификация (с учетом учетных данных выдает токены)
- Добавьте требования в токены, такие как: объемы клиента (под клиентом я имею в виду приложение, выполняющее запрос), идентификатор клиента (под клиентом я имею в виду человека, использующего приложение)
Мы также представили роль шлюза API, который централизует внешний доступ к нашим услугам. API Gateway предоставляет функции, которые не требуют глубоких знаний о внутренних доменах, таких как:
- Обратный прокси-сервер: направляет входящие запросы в соответствующий внутренний сервис
- Управление версиями: версия API-шлюза сопоставляется с различными версиями внутренних служб
- Аутентификация: клиентские запросы включают токен, выданный Identity Server, а API-шлюз проверяет токен (убедитесь, что пользователь - тот, кто говорит, что он есть)
- Регулирование: ограничение количества запросов на клиента
авторизация
Что касается авторизации, она управляется не в API-шлюзе, а во внутренних сервисах. В настоящее время мы делаем 2 основных типа авторизации:
- Авторизация на основе клиентских областей. Пример: клиент (внешнее приложение, потребляющее наши API-интерфейсы) требует наличия области «бронирования» для доступа к конечным точкам API службы бронирования.
- Авторизация на основе клиента. Пример: только если клиент (физическое лицо, использующее приложение) является участником бронирования, может получить доступ к конечной точке GET / бронированиям из службы бронирования.
Чтобы иметь возможность обрабатывать авторизацию во внутренних сервисах, API-шлюз просто пересылает токен (при маршрутизации запроса во внутреннюю службу), который включает в себя как информацию о клиенте (приложение, выполняющее запрос), так и о клиенте в качестве заявки (в те случаи, когда человек регистрируется в клиентском приложении).
Описание проблемы
Пока все хорошо, пока мы не ввели межсервисную связь (некоторые службы могут связываться с другими службами для получения некоторых данных).
Вопрос
Как мы должны подходить к авторизации в межсервисных коммуникациях?
Варианты рассматриваются
Чтобы обсудить различные варианты, я буду использовать следующий пример сценария:
- У нас есть внешнее приложение с именем ExternalApp, которое обращается к нашему API ( ExternalApp может рассматриваться как клиент ) для создания потока бронирования.
- ExternalApp необходим доступ к службе бронирования , поэтому мы предоставляем ExternalApp область «бронирования».
- Внутренне (это что-то совершенно прозрачное для ExternalApp ) служба Бронирования получает доступ к сервису Сервисов для получения услуг бронирования по умолчанию, таких как авиабилеты, страховки или прокат автомобилей
При внутреннем обсуждении этого вопроса всплыло несколько вариантов, но мы не уверены, какой из них лучше:
- Когда бронирования взаимодействуют со службами , он должен просто переслать исходный токен, который он получил от шлюза API (указывая, что клиентом является ExternalApp )
- Последствия: нам может потребоваться предоставить области ExternalApp, которые не должны были предоставляться. Пример: ExternalApp может потребоваться как область «бронирования», так и «услуги», в то время как достаточно только области «бронирования»
- Когда Bookings связывается со Службами , он пересылает токен, указывающий, что клиент теперь стал Bookings (вместо ExternalApp ) + он добавляет утверждение, указывающее, что Bookings олицетворяет собой первоначальный клиент ExternalApp.
- Также включая информацию о том , что оригинальный клиент является ExternalApp на услугах служба может также сделать логику таких как отфильтровывать некоторые услуги в зависимости от исходного вызывающего абонента (например , для внутренних приложений , мы должны вернуть все бои, для внешних приложений только некоторые)
- Службы не должны общаться друг с другом (поэтому мы не должны даже сталкиваться с этим вопросом)
Спасибо заранее за ваш вклад.
источник
Ответы:
Я советую вам иметь внутренний канал связи между микросервисами.
Например, использовать какой-либо брокер сообщений, например, RabbitMQ, для отправки / получения или публикации / подписки сообщений между микросервисами.
Тогда ваш первый конечный пользователь, обращающийся к службе «в вашем примере, служба бронирования», будет отвечать за проверку токена и разрешать клиенту выполнять эту конкретную операцию, возможно, путем связи с IdentityServer.
Затем он будет связываться со службой Сервисов через брокер сообщений, и в этом случае нет необходимости снова проверять токен.
Я думаю, что эта модель будет проще и даст вам лучшую производительность.
источник