2013-04-08 16 views
6

Buduję off z a previous discussion I had with Jon Skeet.Dlaczego nie mogę ufać GUID wygenerowanemu przez klienta? Czy traktowanie PK jako złożonego klienta-GUID i GUID serwera rozwiązuje cokolwiek?

Istotą mojego scenariusza jest następująca:

  • aplikacja Klient ma możliwość tworzenia nowych obiektów „PlaylistItem”, które muszą być utrwalone w bazie danych.
  • Przypadek użycia wymaga, aby element PlaylistItem został utworzony w taki sposób, aby klient nie musiał czekać na odpowiedź z serwera przed wyświetleniem elementu PlaylistItem.
  • Klient generuje identyfikator UUID dla PlaylistItem, pokazuje PlaylistItem w kliencie, a następnie wydaje polecenie zapisu na serwerze.

W tym momencie rozumiem, że niewłaściwym zwyczajem byłoby używanie identyfikatora UUID wygenerowanego przez klienta jako PK obiektu w mojej bazie danych. Powodem tego jest to, że złośliwy użytkownik może modyfikować wygenerowany identyfikator UUID i wymuszać kolizje PK na moim DB.

Aby złagodzić wszelkie szkody, które mogą powstać w wyniku wymuszenia kolizji PK w PlaylistItem, zdecydowałem się zdefiniować PK jako połączenie dwóch identyfikatorów - generowanego przez klienta identyfikatora UUID i wygenerowanego przez serwer identyfikatora GUID. Identyfikator GUID generowany przez serwer jest identyfikatorem listy odtwarzania PlaylistItem.

Od pewnego czasu używam tego rozwiązania, ale nie rozumiem, dlaczego moje rozwiązanie jest lepsze niż zaufanie do identyfikatora klienta. Jeśli użytkownik jest w stanie wymusić kolizję PK z obiektami PlaylistItem innego użytkownika, to sądzę, że powinienem założyć, że może to być PlaylistId tego użytkownika. Mogą nadal wymuszać collisons.

Więc ... tak. Jaki jest właściwy sposób robienia czegoś takiego? Zezwalaj klientowi na utworzenie UUID, serwer daje kciuk w górę/w dół po pomyślnym zapisaniu. Jeśli zostanie wykryta kolizja, należy cofnąć zmiany klienta i wykryć wykrycie kolizji?

Odpowiedz

2

Miłym rozwiązaniem byłoby następujące: Cytując Sam Newmana "Building Microservices":

System powołanie byłoby POST BatchRequest, może przechodzącą w miejscu, w którym plik może być umieszczony z wszystkimi danymi. Usługa klienta zwróci kod odpowiedzi HTTP 202, co oznacza, że ​​żądanie zostało zaakceptowane, ale nie zostało jeszcze przetworzone. System dzwoni może następnie sondować oczekujące zasobów aż pobiera 201 Utworzony wskazując, że żądanie zostało spełnione

Więc w twoim przypadku, można pocztą na serwerze, ale natychmiast uzyskać odpowiedź w stylu „będę oszczędzać PlaylistItem i obiecuję, że będzie to Id ". Klient (i użytkownik) może następnie kontynuować, podczas gdy serwer (może nawet API, ale niektóre procesory w tle, które otrzymały wiadomość od API) potrzebuje czasu na przetworzenie, zatwierdzenie i wykonanie innej, możliwie ciężkiej logiki, dopóki nie zapisze encji. Jak wcześniej wspomniano, interfejs API może dostarczyć punkt końcowy GET dla statusu tego żądania, a klient może go odpytać i podjąć odpowiednie działania w przypadku błędu.

1

Możesz można zaufania UUID generowany przez klienta lub podobny globalny unikatowy identyfikator na serwerze. Po prostu rób to rozsądnie.

Większość twoich tabel/kolekcji będzie również zawierać ID użytkownika lub będzie w stanie powiązać się z ID użytkownika poprzez FK.

Jeśli robisz wstawkę, a złośliwy użytkownik używa istniejącego klucza, wstawienie nie powiedzie się, ponieważ rekord/dokument już istnieje.

W przypadku aktualizacji należy sprawdzić, czy zalogowany użytkownik jest właścicielem tego rekordu lub jest uprawniony (na przykład administrator) do aktualizacji. Jeśli wymuszane jest prawo własności (tj. Nie ma scenariusza administratora), wówczas klauzula where znajdująca rekord/dokument zawiera zarówno identyfikator, jak i identyfikator użytkownika. Teraz technicznie identyfikator użytkownika jest nadmiarowy w klauzuli where, ponieważ Id będzie jednoznacznie znajdował jeden rekord/dokument. Jednak dodanie identyfikatora użytkownika sprawia, że ​​rekord należy do użytkownika, który robi aktualizację, a nie do złośliwego użytkownika.

Zakładam, że istnieje szyfrowany token lub sesja jakiegoś rodzaju, że serwer odszyfrowuje, aby ustalić identyfikator użytkownika i że nie jest on dostarczany przez klienta, w przeciwnym razie nie jest to bezpieczne.