Czy mozna obejść się bez UUID

0

Czy konieczne jest używanie UUID czy samo ID wystarczy i można to jakoś zabezpieczyć?

Chodzi mi o to że np przy autoryzacji użytkownika można użyać tylko ID i tylko ID się posługiwać ?

9

Chyba powinieneś trochę więcej kontekstu napisać. Tak postawione pytanie nie ma sensu.

  1. Oczywiście, że samo ID wystarczy -> w pewnych systemach. Czasem wystarczy nawet dokłanie jedno ID = 42, a nawet i bez tego jednego ID można się obyć.
  2. Przed czym zabezpieczyć?
3

Używając UUID łatwiej wyskalujesz aplikację np w chmurze, bo możesz bez synchronizacji między serwerami nadawać nowe ID-ki praktycznie bez martwienia się że został już w międzyczasie użyty na serwerze np w innym kraju. Widziałem obejścia tego w stylu że jeden node generuje ID-ki parzyste a drugi nieparzyste, przy stałej liczbie serwerów znając ich liczbę można to zrobić w ten sposób, ewentualnie dodać inny offset na każdym serwerze.

Dodatkowo możesz zrobić aplikację offline - wszystko może dziać się po stronie klienta, nawet dość skomplikowana logika a potem przy zapisie to wpisujesz do bazy, też nie martwiąc się że ID-ki w międzyczasie zostały zajęte. To też można ominąć przy odrobinie dodatkowej pracy, można zrobić mapowania wirtualnych IDków na wewnętrzne, ale to dużo bardziej skomplikowane.

Trzecim plusem UUID jest wyżej wspomniane bezpieczeństwo - nie musisz się martwić że userzy zgadną ID kolejnego resource'a. To też można rozwiązać np szyfrując ID lub mapując wewnętrzne ID na zewnętrzne, czyli każdy resource musi tak naprawdę dostać dwa ID-ki.

Jedynym minusem UUID jest nadmiarowa ilość przesyłanych danych i wolniejsze zapytania SQL, na przykład grupowanie po uuid będzie nieco wolniejsze i będzie wymagało więcej pamięci niż po 4 bajtowym IDku. Oszczędza za to dużo pracy i umożliwia bardziej skomplikowane scenariusze.

2
TakMaszRacje napisał(a):

Czy konieczne jest używanie UUID czy samo ID wystarczy i można to jakoś zabezpieczyć?

Używaj tylko jednego idka. Im więcej rodzajów tym większy burdel i wprowadzenie czegoś takiego musi mieć jakieś wytłumaczenie. Jak wiesz, że potrzebujesz UUID to nie trzymaj numerycznego IDKa tylko niech UUID będzie kluczem w bazie.

obscurity napisał(a):

Jedynym minusem UUID jest nadmiarowa ilość przesyłanych danych i wolniejsze zapytania SQL, na przykład grupowanie po uuid będzie nieco wolniejsze i będzie wymagało więcej pamięci niż po 4 bajtowym IDku. Oszczędza za to dużo pracy i umożliwia bardziej skomplikowane scenariusze.

Głównym argumentem przeciwko UUID jest ich losowość, co sprawia, że słabo pasują do BTree indeksu. Polecam dokument o dość nowych wersjach UUID, które opisują dobrze ten problem https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html

0

W niektórych systemach nawet brak id by wystarczył. Jeśli operujemy tylko na danych, które nie mogą mieć powtórzeń, np mamy aplikację w której użytkownicy są indetyfikowani np używając PESEL; ponieważ dwie osoby nie mogą mieć tego samego PESEL, wtedy możemy użyć tego numeru do unikanlnego znalezienia użytkownika. Id również nie potrzebujemy, kiedy nie musimy nigdy identyfikować konkretnego rekordu, np. tabele łącznikowe w bazach relacyjnych też nie mają id, bo i po co?

Odn. @KamilAdam: Oczywiście nie mówię tutaj, że pesel to jest dobry substytut, i należy go od razu ustawiać jako PRIMARY KEY, tylko ilustruję po co jest id - po to żeby uniknalnie zidentyfikować record, są przypadki kiedy mamy takie pole w recordach, i ono wystarczy. Są też przypadki kiedy takiego nie ma, i musimy dodać pole w bazie tylko do tego celu. Dodatkowo, niewiele osób się zastanawia nad tym po co jest id, i po prostu dodaje je z automatu, jest to częsta praktyka.

Skąd więc wiadomo, kiedy użyć id, a kiedy nie. Wtedy, kiedy potrzebujemy odnieść się do jakiegoś recordu, ale w tym recordzie nie ma żadnych danych po których jest 100% pewności że można po nich unikalnie zidentyfikować record (czyli pewnie 95% przypadków i więcej). Zwykły integer wystarczy, jeśli mamy pojedynczą bazę. Taki id może nadać aplikacja, lub niektóre bazy (albo może nawet wszystkie?) mają wbudowane funkcje, które mogą same nadawać kolejny integer (auto increament).

Co jest złego z id? W aplikacjach z pojedynczą bazą - nic.

Jeśli jednak więcej niż jedna aplikacja ma dostęp do jednej bazy, albo przetwarzanie takich danych jest rozproszone; wtedy możę dojść do sytuacji w której dwie aplikacje będą chciały wygenerować nowy id, (np kolejny to 43), i obie będą chciały go dodać. Spowoduje to niekonsystencje systemu. Można oczywiście próbować to obejść; np pozwolić jednej aplikacji, drugiej odrzucić, i niech druga wybierze nowy id; ale to jest słabe rozwiązanie. Lepiej wygenerować taki id, którego szansa na powtórzenie jest bardzo niska lub zerowa, i tutaj wchodzi uuid.

3

Co do numeru PESEL to faktycznie w teorii jest unikalny. A w praktyce były przypadki że PESEL się powtarzał. W dodatku PESEL koduje płeć więc w przypadku zmiany płci zmienia się też PESEL (rzadkie, ale się zdarza). Gorsze jest że PESEL to dana osobowa więc trzeba uważać z użyciem :D

Co do wydajności id numerycznego vs UIDD. W Postgresie integer (int4) zajmuje 32 bity, bigint (int8) - 64 bity, a UUID zajmuje 128 bitów. więc różnica IMHO niewielka. Oczywiście jak używamy prymitywną bazę która nie ma tyku UUID to jest gorzej :D
Ale trzeba tez pamiętać że UUID nie daje pełnej losowości. Nie po to był projektowany. Podstawową ideą było to żeby numery się nie powtarzały, a nie zapewnienie nieprzewidywalności numerów
BTW istnieją conajmniej 4 sposoby generacji UUIDów i jeden z nich zapewnia że kolejne UUIDy będą rosnące co może być przydatne przy niektórych zapytaniach, ale znów zmniejsza losowość

To tyle jeśli używa się normalnej, tradycyjnej bazy danych jak PostgreSQL. Jak się używa jakiegoś NoSQL jak Cassandra to UUID jest obowiązkowy. Bo w Cassandra jest dynamiczna ilość węzłów nadających UUIDy

0
KamilAdam napisał(a):

Co do wydajności id numerycznego vs UIDD. W Postgresie integer (int4) zajmuje 32 bity, bigint (int8) - 64 bity, a UUID zajmuje 128 bitów. więc różnica IMHO niewielka. Oczywiście jak używamy prymitywną bazę która nie ma tyku UUID to jest gorzej :D

a oracle to w ogóle ma typy liczbowe chyba zmiennej długości :)

https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/Data-Types.html#GUID-9401BC04-81C4-4CD5-99E7-C5E25C83F608

NUMBER Data Type
The NUMBER data type stores zero as well as positive and negative fixed numbers with absolute values from 1.0 x 10-130 to but not including 1.0 x 10126. If you specify an arithmetic expression whose value has an absolute value greater than or equal to 1.0 x 10126, then Oracle returns an error. Each NUMBER value requires from 1 to 22 bytes.

nie testowałem, ani nie czytałem o wydajności typów liczbowych w oracle'u. na oko i tak nie wyglądają na demony szybkości, więc skoro oracle się nie martwi, to po co ja mam się martwić dodatkowo? :)

2

@TakMaszRacje: mówiąc o ID, masz zapewne na myśli liczbę całkowitą generowaną przez jakąś sekwencję. Przy takim założeniu, to jak pisał @jarekr000000 trafiasz na problemy z przewidywalnością numerów i analiza aplikacji staje się prostsza. Pytanie, jak jeszcze wykorzystujesz takie ID? Czy jest ono podstawą do sortowania danych w czasie prezentacji? Jeżeli tak, to zrobiłeś sobie krzywdę w naprawdę paskudny sposób. Jeżeli jednak nie ma żadnego innego zastosowania, to możesz użyć UUID. Otrzymasz wtedy pseudolosowy, unikalny i niesortowalny identyfikator.

I w tym momencie ci zamieszam :)

Jeżeli jednak potrzebujesz używać identyfikatora do sortowania, to zamiast sekwencyjnego ID użyj ULID, czyli odmiany UUID, która jest w pewnym zakresie sortowalna. W tym momencie użytkownicy będą mogli zostać uszeregowani, pod warunkiem że nie pojawi się dwóch stworzonych w tej samej milisekundzie, według czasu powstania. Identyfikator będzie pseudolosowy, więc jedyne co będzie można powiedzieć o aplikacji na jego podstawie, to kiedy dany użytkownik został utworzony. Jednak nie będzie można w łatwy sposób znaleźć kolejnego/poprzedniego identyfikatora.

0

Czy konieczne jest używanie UUID czy samo ID wystarczy i można to jakoś zabezpieczyć?

Nie jest konieczne używanie UUIDa (identyfikatora unikalnego w czasie i przestrzeni), ale bywa czasem potrzebne, np. jak robisz system rozproszony i masz do rozwiązania problem unikalności identyfikatorów. Tak jak z "volatile", jak będziesz potrzebował, to będziesz wiedział dlaczego ;)

Chodzi mi o to że np przy autoryzacji użytkownika można użyać tylko ID i tylko ID się posługiwać ?

Autoryzację (sprawdzenie uprawnień do zasobu/akcji) mylisz z uwierzytelnieniem (weryfikacją, czy użytkownik jest tym za kogo się podaje).

W Spring Security masz możliwość stworzenia własnego AuthenticationProvider , więc jeśli w systemie masz użtykowników zapisanych w jakiejś tabelce jako : MY_USER (ID_Z_SEKWENCJI, DATA_URODZENIA, NR_TELEFONU, ...., to w procesie uwierzytelnienia (logowania) nie masz potrzeby korzystania z tego IDka i wystawiania go na świat. Uwierzytelnienie może być realizowane w oparciu o NR_TELEFONU + SMS z kodem, albo o certyfikat SSL klienta, itp.

1 użytkowników online, w tym zalogowanych: 0, gości: 1