Uwierzytelnianie interfejsu API REST


181

Buduję aplikację, która będzie hostowana na serwerze. Chcę zbudować interfejs API dla aplikacji, aby ułatwić interakcję z dowolnej platformy (aplikacja internetowa, aplikacja mobilna). Nie rozumiem tego, że w przypadku używania interfejsu API REST, w jaki sposób uwierzytelniamy użytkownika.

Na przykład, gdy użytkownik zaloguje się, a następnie chce utworzyć temat na forum. Skąd mam wiedzieć, że użytkownik jest już zalogowany?


4
Prawdopodobnie powinieneś tutaj wyszukać „uwierzytelnianie REST”. Zostało to omówione w wielu innych pytaniach.
Brian Kelly,

10
W skrócie, pozwól klientowi wysyłać nazwę użytkownika i hasło przy każdym żądaniu za pomocą HTTP Basic Auth (przez SSL!) Lub uwierzytelnij się raz, aby klient miał uwierzytelnioną sesję, która wygaśnie po pewnym okresie bezczynności (lub jednak zdecydujesz się zastąpić obsługa sesji twojego frameworka). Wspomniana sesja może być następnie zapisana w pliku cookie lub być parametrem przekazywanym przy każdym żądaniu (np. JSESSIONID w środowisku Java).
opyate


@opyate Z punktu widzenia bezpieczeństwa nie jest dobrym pomysłem, aby sesja była obsługiwana przy użyciu plików cookie w przypadku interfejsu API REST, ponieważ osoby atakujące mogą wysyłać żądania bez zgody użytkownika. Lepiej dołączyć skrót sesji lub token do nagłówka HTTP (np. Autoryzacja).
s3v3n

1
@ s3v3n Popraw mnie, jeśli się mylę, ale zarówno twoje, jak i moje sugestie to po prostu różne sposoby korzystania z kombinacji nagłówka + pamięci lokalnej, aby uzyskać to samo. Jest to Authorizationnagłówek + np. Nagłówek localStorage VS w Cookieprzeglądarce + standardowe przechowywanie plików cookie w przeglądarce.
opyate

Odpowiedzi:


72

Możesz użyć uwierzytelniania podstawowego lub szyfrowanego HTTP. Możesz bezpiecznie uwierzytelniać użytkowników za pomocą protokołu SSL, jednak spowalnia to nieco interfejs API.

  • Uwierzytelnianie podstawowe - wykorzystuje kodowanie Base64 dla nazwy użytkownika i hasła
  • Uwierzytelnianie szyfrowane - szyfruje nazwę użytkownika i hasło przed wysłaniem ich przez sieć.

OAuth jest najlepszym, co można uzyskać. Zaletami oAuth jest token, który można odwołać lub wydłużyć. Zobacz, jak wdrożyć: Link roboczy z komentarzy: https://www.ida.liu.se/~TDP024/labs/hmacarticle.pdf


4
Przeczytaj to pytanie i odpowiedź udzieloną przez Les Hazelwood (autor Apache Shiro).
justin.hughey

1
Przydatny link, w jaki sposób Twitter chroni swój interfejs API REST: Zabezpieczenia interfejsu API REST w serwisie Twitter
WildDev

Ponieważ jest to zaakceptowana odpowiedź, uważam, że ważne jest, aby wspomnieć, że możesz także używać uwierzytelniania Digest. Przeczytaj o różnicach między uwierzytelnianiem podstawowym a uwierzytelniającym tutaj: stackoverflow.com/questions/9534602/...
Rayee Roded

116

Na przykład, gdy użytkownik ma login. Teraz powiedzmy, że użytkownik chce utworzyć temat na forum. Skąd mam wiedzieć, że użytkownik jest już zalogowany?

Pomyśl o tym - musi być jakiś uścisk dłoni, który mówi Twojemu interfejsowi API „Utwórz forum”, że to bieżące żądanie pochodzi od uwierzytelnionego użytkownika. Ponieważ interfejsy API REST są zwykle bezstanowe, stan musi gdzieś zostać utrwalony . Twój klient korzystający z interfejsów API REST jest odpowiedzialny za utrzymanie tego stanu. Zwykle jest to jakiś token, który jest przekazywany od momentu zalogowania użytkownika. Jeśli token jest dobry, Twoje żądanie jest dobre.

Sprawdź, jak Amazon AWS wykonuje uwierzytelnienia. To doskonały przykład „przekazywania złotówki” z jednego interfejsu API na inny.

* Pomyślałem o dodaniu praktycznej odpowiedzi do mojej poprzedniej odpowiedzi. Wypróbuj Apache Shiro (lub dowolną bibliotekę uwierzytelniania / autoryzacji). Podsumowując, staraj się unikać niestandardowego kodowania. Po zintegrowaniu ulubionej biblioteki (używam Apache Shiro, btw) możesz wykonać następujące czynności:

  1. Utwórz interfejs logowania / wylogowania, taki jak: /api/v1/loginiapi/v1/logout
  2. W tych interfejsach API logowania i wylogowania wykonaj uwierzytelnianie w sklepie użytkownika
  3. Wynikiem jest token (zwykle JSESSIONID) wysyłany z powrotem do klienta (internet, telefon komórkowy, cokolwiek)
  4. Od tego momentu wszystkie kolejne połączenia wykonywane przez klienta będą zawierać ten token
  5. Załóżmy, że Twoje następne połączenie jest wykonywane do interfejsu API o nazwie /api/v1/findUser
  6. Pierwszą rzeczą, którą zrobi ten kod API, będzie sprawdzenie tokena („czy ten użytkownik jest uwierzytelniony?”)
  7. Jeśli odpowiedź wróci jako NIE, wówczas rzucasz status HTTP 401 z powrotem na klienta. Niech sobie z tym poradzą.
  8. Jeśli odpowiedź brzmi TAK, przejdź do zwrócenia żądanego użytkownika

To wszystko. Mam nadzieję że to pomoże.


Więc to, co opisujesz, jest w zasadzie ciasteczkiem sesyjnym, prawda?
LordOfThePigs,

tak, ale sesja jest „utrzymywana” w 2 różnych miejscach. Jeden na serwerze API, drugi w przeglądarce. Odpowiedź JSON (lub cokolwiek innego) z powrotem na pomyślne logowanie przeglądarki powinna przekazać identyfikator sesji na serwerze API z powrotem do przeglądarki. Sesjami tymi zarządzają niezależnie ich agenci.
Kingz

11
Wierzę, że Kingz próbował przekazać pomysł, że mechanizm utrzymywania sesji jest celowo niejasny. Sesyjny plik cookie to tylko jedna implementacja tego mechanizmu.
justin.hughey

2
@Kingz, co z bezpieczeństwem w tym rozwiązaniu, na przykład, jeśli haker wącha link z session_id i zaczyna wysyłać żądania, które treści są poprawne session_id? Możemy to rozwiązać, dodając ssl do połączenia z serwerem, ale co z klientami?
Ahmad Samilo,

1
jak zapobiec porwaniu sesji w przypadku man-in-the-middle-attrack?
m0z4rt

38
  1. Użyj uwierzytelniania podstawowego HTTP do uwierzytelniania klientów, ale traktuj nazwę użytkownika / hasło tylko jako tymczasowy token sesji .

    Token sesji jest tylko nagłówkiem dołączonym do każdego żądania HTTP, np .: Authorization: Basic Ym9ic2Vzc2lvbjE6czNjcmV0

    Ciąg Ym9ic2Vzc2lvbjE6czNjcmV0 powyżej jest tylko ciągiem „bobsession1: s3cret” (który jest nazwą użytkownika / hasłem) zakodowanym w Base64.

  2. Aby uzyskać powyższy token sesji tymczasowej, podaj funkcję API (np . http://mycompany.com/apiv1/login:), która pobiera nazwę użytkownika i hasło administratora jako dane wejściowe, tworzy tymczasową nazwę użytkownika / hasło uwierzytelniania podstawowego HTTP po stronie serwera i zwraca token (np .: Ym9ic2Vzc2lvbjE6czNjcmV0). Ta nazwa użytkownika / hasło powinno być tymczasowe, powinno wygasnąć po około 20 minutach.

  3. Aby zwiększyć bezpieczeństwo, upewnij się, że usługa REST jest obsługiwana przez HTTPS, aby informacje nie były przesyłane jako zwykły tekst

Jeśli korzystasz z Javy, biblioteka Spring Security zapewnia dobrą obsługę implementacji powyższej metody


1
Dlaczego wygasa po 20 minutach? co jeśli jest to strona internetowa taka jak Facebook, że logowanie jest do momentu wylogowania użytkownika?
Dejell

1
@dejel Miałem założenie, że „sesja” ma charakter tymczasowy. Często wygasa, jeśli użytkownik jest na biegu jałowym
gerrytan

Do czego służy Base64? Możesz po prostu zwrócić tymczasowe hasło. W obu przypadkach tak naprawdę ważne jest to, że to tymczasowe hasło jest silne. Sprawdź security.stackexchange.com/a/19686/72945
e18r

7

Myślę, że najlepszym rozwiązaniem jest użycie OAuth2. Google go, a znajdziesz wiele przydatnych postów, które pomogą Ci to skonfigurować.

Ułatwi to tworzenie aplikacji klienckich dla Twojego interfejsu API z aplikacji internetowej lub mobilnej.

Mam nadzieję, że to ci pomoże.


2
Przeczytaj to pytanie i odpowiedź Les Hazelwood (autor Apache Shiro).
justin.hughey

0

Korzystam z uwierzytelniania JWT. Działa dobrze w mojej aplikacji.

Istnieje metoda uwierzytelniania, która wymaga poświadczeń użytkownika. Ta metoda sprawdza poprawność poświadczeń i zwraca token dostępu w przypadku powodzenia.

Ten token musi zostać wysłany do każdej innej metody w moim interfejsie API sieci Web w nagłówku żądania.

Jest dość łatwy do wdrożenia i bardzo łatwy do przetestowania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.