Pierwszoplanowy
Przechodzimy z platformy monolitycznej do architektury zorientowanej na usługi. Stosujemy bardzo podstawowe zasady DDD i dzielimy naszą domenę na różne ograniczone konteksty. Każda domena jest dystrybuowana i udostępnia usługę za pośrednictwem interfejsu API sieci Web (REST).
Ze względu na charakter naszej działalności, mamy takie usługi jak rezerwacjach , usług , klientów , produktów , itp
Stworzyliśmy również serwer tożsamości (oparty na Thinktecture Identity Server 3), którego główną rolą jest:
- Scentralizuj uwierzytelnianie (dane uwierzytelniające wydaje tokeny)
- Dodaj oświadczenia do tokenów, takie jak: zakresy klienta (jak na klienta, mam na myśli aplikację wykonującą żądanie), identyfikator klienta (na klienta, mam na myśli osobę korzystającą z aplikacji)
Wprowadziliśmy również rolę API Gateway, która centralizuje zewnętrzny dostęp do naszych usług. API Gateway zapewnia funkcjonalności, które nie wymagają dogłębnej znajomości domen wewnętrznych, takie jak:
- Odwrotny serwer proxy: kieruje przychodzące żądania do odpowiedniej usługi wewnętrznej
- Wersjonowanie: wersja interfejsu API Gateway odwzorowuje różne wersje usług wewnętrznych
- Uwierzytelnianie: żądania klientów zawierają token wydany przez serwer tożsamości, a brama API sprawdza token (upewnij się, że użytkownik jest tym, kto twierdzi, że jest)
- Ograniczanie: ogranicz liczbę żądań na klienta
Upoważnienie
Co dotyczy autoryzacji, nie jest ona zarządzana w bramce API, ale w samych usługach wewnętrznych. Obecnie wykonujemy 2 główne rodzaje autoryzacji:
- Autoryzacja na podstawie zakresów klienta. Przykład: klient (zewnętrzna aplikacja zużywa nasze API) wymaga zakresu „rezerwacje” na dostęp do rezerwacji hoteli usługowa punktów końcowych API
- Autoryzacja na podstawie klienta. Przykład: jeśli tylko klient (osoba fizyczna przy użyciu aplikacji) jest uczestnikiem rezerwacji można uzyskać dostęp do punktu końcowego GET / rezerwacje od Kartki usługi
Aby móc obsługiwać autoryzację w usługach wewnętrznych, brama API po prostu przekazuje token (podczas routingu żądania do usługi wewnętrznej), który zawiera zarówno informacje o kliencie (aplikacji wykonującej żądanie), jak i kliencie jako roszczenie (w przypadki, w których osoba jest zalogowana w aplikacji klienckiej).
Opis problemu
Jak dotąd tak dobrze, dopóki nie wprowadziliśmy komunikacji między usługami (niektóre usługi mogą komunikować się z innymi usługami w celu uzyskania niektórych danych).
Pytanie
Jak powinniśmy podejść do autoryzacji w komunikacji między usługami?
Rozważane opcje
Aby omówić różne opcje, wykorzystam następujący przykładowy scenariusz:
- Mamy zewnętrzną aplikację o nazwie ExternalApp, która uzyskuje dostęp do naszego interfejsu API ( ExternalApp może być postrzegany jako klient ) w celu zbudowania przepływu rezerwacji
- ExternalApp potrzebuje dostępu do usługi Bookings , dlatego przyznajemy ExternalApp zakres „rezerwacji”
- Wewnętrznie (jest to coś całkowicie przezroczysty dla ExternalApp ) Kartki serwis acesses Services usługę w celu uzyskania usługi domyślne rezerwacji takich jak loty, ubezpieczeniach lub wynajem samochodu
Podczas wewnętrznego omawiania tego problemu pojawiło się kilka opcji, ale nie jesteśmy pewni, która opcja jest najlepsza:
- Gdy Bookings komunikuje się z Usługami , powinien po prostu przesłać oryginalny token, który otrzymał od API Gateway (wskazując, że klient jest aplikacją zewnętrzną )
- Konsekwencje: być może będziemy musieli przyznać zakresy aplikacji zewnętrznej, które nie powinny były zostać przyznane. Przykład: ExternalApp może wymagać zarówno zakresu „rezerwacji”, jak i „usług”, podczas gdy wystarczyłby tylko zakres „rezerwacji”
- Gdy Bookings komunikuje się z Usługami , przesyła token wskazujący, że klient stał się Bookings (zamiast ExternalApp ) + dodaje roszczenie wskazujące, że Bookings podszywa się pod oryginalnego klienta ExternalApp
- Włączając również informacje, że oryginalny klient jest ExternalApp z Usługi obsługa mogłaby również zrobić logiki takich jak filtrowanie niektórych usług w zależności od pierwotnego dzwoniącego (np wewnętrznych aplikacji powinniśmy zwrócić wszystkie pojedynki, dla zewnętrznych aplikacji tylko niektóre)
- Usługi nie powinny się ze sobą komunikować (więc nie powinniśmy nawet stawiać czoła temu pytaniu)
Z góry dziękuję za Twój wkład.
źródło
Odpowiedzi:
Radzę mieć wewnętrzny kanał komunikacji między mikrousługami.
Na przykład, aby użyć wewnętrznego brokera wiadomości, takiego jak RabbitMQ, do wysyłania / odbierania lub publikowania / subskrybowania wiadomości między mikrousługami.
Wtedy Twoja pierwsza usługa skierowana do użytkownika końcowego „na przykład usługa rezerwacji” będzie odpowiedzialna za sprawdzenie tokena i upoważnienie klienta do wykonania tej konkretnej operacji może być przez komunikację z IdentityServer.
Następnie komunikuje się z usługą za pośrednictwem brokera wiadomości, w takim przypadku nie ma potrzeby ponownej weryfikacji tokena.
Myślę, że ten model będzie prostszy i zapewni lepszą wydajność.
źródło