integralność danych dzięki dedykowanym bazom danych w aplikacji .NET Core Api

Bezpieczeństwo danych: aplikacja multi tenant .Net Core api

W naszym projekcie jednym z wymagań biznesowych było zapisywanie i trzymanie danych klientów w oddzielnych bazach danych. Potrzebowaliśmy oddzielić je ze względu na integralność danych i bezpieczeństwo. Jak poradziliśmy sobie z tym problemem? Wykorzystując architekturę multi-tenant.

Marcin Czajński. Lead developer w KPMG. Programista od ponad 10 lat. Zaczął od front-end-u i z biegiem lat swoje zainteresowanie przenosił na kolejne obszary IT, bazy danych, technologie backend-owe (głównie Microsoft). Trwa to nadal i w tym momencie skupia się na rozwiązaniach chmurowych – Azure. W firmie KPMG ma kilka ról. Główna to Lead developer dla grupy zdolnych juniorów. Dodatkowo Scrum Master, Architect i na końcu deweloper.


Takie podejście już wielokrotnie było opisywane w Internecie, np. na stronie Microsoftu. Microsoft dostarcza bibliotekę właśnie do takiego rozwiązania. Niestety dokumentacja nie jest przejrzysta i wymaga przejścia przez wiele przykładów. Mimo wszystko warto się z nią zapoznać.

Po analizie kodu i dokumentacji, zrobieniu kilku testowych koncepcji, zdecydowaliśmy się na napisanie tej funkcjonalności od nowa. Jak się okazało nie było to trudne i czasochłonne, z niewielką ilością nowego kodu. Efekt zamierzony został osiągnięty – bezpieczne dane, które nie mieszają się w ramach jednej aplikacji u kilku klientów.

.Net Core api i jedna baza danych

.net core api z jedną bazą danych

.Net Core api i kilka dedykowanych baz danych

Jedna aplikacja .net core api i kilka baz danych per klient.

.net core api i kilka baz danych

Implementacja

Zgodnie z tym tutorialem dodajemy db context do naszego projektu. Nasza metoda ConfigureServices w klasie Startup wygląda teraz następująco:

Jeśli najedziesz wskaźnikiem myszy na metodę AddDbContext wyświetli się następująca podpowiedź:

integralność danych - AddDbContext w architekturze multi-tenant

Według informacji, czas życia obiektu db context jest wskazany w scope. Co to znaczy dla nas? Tworzymy db context obiekt dla każdego zapytania http. Możesz więcej o tym poczytać tutaj. W tym miejscu wprowadzimy potrzebne dla nas zmiany.

Zmodyfikujmy następująco powyższy kod:

Jest to takie samo podejście napisane inaczej. Jak widzisz jest użyta metoda AddScoped, która akceptuje funkcje. Dzięki temu mamy więcej kontroli nad tym, co się tutaj dzieje.

DbContext akceptuje obiekt DbContextOptions, gdzie dostarczamy połączenie do bazy danych pobierane z konfiguracji, pliku app settings.json. Wiedząc to możemy dynamicznie to połączenie zmieniać w zależności od tego, co znajdziemy w zapytaniu http, np. w nagłówku.

Nasz plik konfiguracyjny może wyglądać następująco:

Teraz mamy zdefiniowane trzy połączenia do bazy danych, dla każdego klienta. Dodajmy klasę TodoContextOptionsBuilder, która dziedziczy po interfejsie ITodoContextOptionsBuilder.

Interfejs ITodoContextOptionsBuilder ma tylko jedną właściwość do zaimplementowania. Kod znajdziemy w klasie TodoContextOptionsBuilder. Ta klasa zwraca opcje połączenia bazodanowego w zależności od informacji jakie mamy w nagłówku Tenant-Id zapytania http.

Na podstawie nagłówka Tenant-Id możemy znaleźć odpowiednie połączenie do bazy danych w pliku konfiguracyjnym.

Metoda ConfigurationService w klasie Startup wygląda teraz następująco:

Jak widzisz obiekt typu TodoContextOptionsBuilder jest również tworzony jako scoped.

Podsumowanie

Jak widać, powyższy sposób przyniósł pożądany przez nas efekt. Dla przypomnienia: było nim zapisywanie i trzymanie danych klientów w oddzielnych bazach danych. Co można zrobić więcej?

  1. Warto utworzyć warstwę pośrednią, aby sprawdzać czy zapytanie posiada odpowiedni nagłówek i zwracać wiadomość do użytkownika.
  2. Sprawdzać, czy mamy połączenie do bazy danych dla podanego nagłówka.
  3. Jeśli chcemy posiadać bazę danych Catalog, która trzyma informacje o klientach, warto użyć cache.
  4. Jeśli korzystasz z Azure SQL Database przydatnym rozwiązaniem będzie elastic pools.
    https://docs.microsoft.com/en-us/azure/azure-sql/database/elastic-pool-overview.

Wszystkie obrazki użyte (ewentualnie lekko zmodyfikowane) w tym artykule pochodzą z tej strony.

Zdjęcie główne artykułu pochodzi z unsplash.com.

Zapraszamy do dyskusji

Patronujemy

 
 
More Stories
Czy Flutter zabłyśnie w 2020 roku? Prasówka Technologiczna 4.01.2020