Zaczynam planować interfejs API REST za pomocą node.js, express i mongodb. Interfejs API zapewnia dane dla strony internetowej (obszar publiczny i prywatny), a może później aplikacji mobilnej. Frontend zostanie opracowany w AngularJS.
Przez kilka dni dużo czytałem o zabezpieczaniu interfejsów API REST, ale nie docieram do ostatecznego rozwiązania. O ile rozumiem, to używanie HTTPS w celu zapewnienia podstawowego bezpieczeństwa. Ale w jaki sposób mogę chronić interfejs API w takich przypadkach użycia:
Tylko odwiedzający / użytkownicy strony / aplikacji mogą uzyskiwać dane dla publicznego obszaru strony / aplikacji
Tylko uwierzytelnieni i autoryzowani użytkownicy mogą uzyskiwać dane dla obszaru prywatnego (i tylko te dane, w których użytkownik udzielił uprawnień)
W tej chwili myślę o zezwoleniu na używanie interfejsu API tylko użytkownikom z aktywną sesją. Aby autoryzować użytkowników, użyję paszportu i aby uzyskać zgodę, muszę coś dla siebie zaimplementować. Wszystko na szczycie HTTPS.
Czy ktoś może zapewnić najlepsze praktyki lub doświadczenia? Czy brakuje mojej „architektury”?
źródło
Odpowiedzi:
Miałem ten sam problem, który opisujesz. Dostęp do strony internetowej, którą tworzę, można uzyskać z telefonu komórkowego i przeglądarki, więc potrzebuję interfejsu API, aby umożliwić użytkownikom rejestrację, logowanie i wykonywanie określonych zadań. Ponadto muszę wspierać skalowalność, ten sam kod działający na różnych procesach / maszynach.
Ponieważ użytkownicy mogą TWORZYĆ zasoby (czyli akcje POST / PUT), musisz zabezpieczyć interfejs API. Możesz użyć oauth lub zbudować własne rozwiązanie, ale pamiętaj, że wszystkie rozwiązania mogą zostać zepsute, jeśli hasło naprawdę łatwo jest znaleźć. Podstawową ideą jest uwierzytelnianie użytkowników przy użyciu nazwy użytkownika, hasła i tokena, zwanego także apitokenem. Ten apitoken można wygenerować za pomocą UUID węzła, a hasło można zaszyfrować za pomocą pbkdf2
Następnie musisz gdzieś zapisać sesję. Jeśli zapiszesz go w pamięci jako zwykły obiekt, jeśli zabijesz serwer i uruchomisz go ponownie, sesja zostanie zniszczona. Ponadto nie jest to skalowalne. Jeśli używasz haproxy do ładowania równowagi między maszynami lub po prostu używasz pracowników, ten stan sesji zostanie zapisany w jednym procesie, więc jeśli ten sam użytkownik zostanie przekierowany do innego procesu / maszyny, będzie musiał ponownie się uwierzytelnić. Dlatego musisz przechowywać sesję we wspólnym miejscu. Zazwyczaj odbywa się to za pomocą redis.
Gdy użytkownik zostanie uwierzytelniony (nazwa użytkownika + hasło + apitoken), wygeneruj kolejny token dla sesji, czyli accesstoken. Znowu z uuid węzła. Wyślij do użytkownika klucz dostępu i identyfikator użytkownika. Identyfikator użytkownika (klucz) i accesstoken (wartość) są przechowywane w pamięci podręcznej z czasem wygaśnięcia, np. 1h.
Teraz za każdym razem, gdy użytkownik wykona dowolną operację przy użyciu interfejsu API reszty, będzie musiał wysłać identyfikator użytkownika i klucz dostępu.
Jeśli zezwolisz użytkownikom na rejestrację przy użyciu pozostałego interfejsu API, musisz utworzyć konto administratora z administracyjnym apitokenem i przechowywać je w aplikacji mobilnej (szyfruj nazwę użytkownika + hasło + apitoken), ponieważ nowi użytkownicy nie będą mieli apitokenu, gdy rejestrują się.
Sieć korzysta również z tego interfejsu API, ale nie trzeba używać apitokens. Możesz użyć express w sklepie redis lub skorzystać z tej samej techniki opisanej powyżej, ale pomijając sprawdzanie apitoken i zwracając użytkownikowi identyfikator użytkownika + dostęp do pliku cookie.
Jeśli masz obszary prywatne, porównaj nazwę użytkownika z dozwolonymi użytkownikami podczas ich uwierzytelniania. Możesz także zastosować role do użytkowników.
Podsumowanie:
Alternatywą bez apitokenu byłoby użycie HTTPS i wysłanie nazwy użytkownika i hasła w nagłówku autoryzacji oraz buforowanie nazwy użytkownika w trybie redis.
źródło
apitoken
? czy to jest hasło „wtórne”?Chciałbym przekazać ten kod jako rozwiązanie strukturalne dla postawionego pytania, zgodnie (mam nadzieję) z przyjętą odpowiedzią. (Możesz to bardzo łatwo dostosować).
Ten serwer można przetestować za pomocą curl:
źródło
Właśnie skończyłem przykładową aplikację, która robi to w dość prosty, ale przejrzysty sposób. Używa mongoose z mongodb do przechowywania użytkowników i paszportu do zarządzania autoryzacją.
https://github.com/Khelldar/Angular-Express-Train-Seed
źródło
Istnieje wiele pytań dotyczących wzorców uwierzytelniania REST tutaj na SO. Oto najbardziej odpowiednie dla twojego pytania:
Zasadniczo musisz wybierać między użyciem kluczy API (najmniej bezpieczny, ponieważ klucz może zostać odkryty przez nieautoryzowanego użytkownika), kombinacji aplikacji i tokena (średni) lub pełnej implementacji OAuth (najbezpieczniejszy).
źródło
Jeśli chcesz zabezpieczyć swoją aplikację, zdecydowanie powinieneś zacząć od HTTPS zamiast HTTP , to zapewnia stworzenie bezpiecznego kanału między tobą a użytkownikami, który zapobiegnie wąchaniu danych przesyłanych tam i z powrotem do użytkowników i pomoże zachować dane wymieniane poufne.
Możesz użyć JWT (JSON Web Tokeny) do zabezpieczenia interfejsów API RESTful , ma to wiele zalet w porównaniu do sesji po stronie serwera, korzyści to głównie:
1- Bardziej skalowalne, ponieważ serwery API nie będą musiały utrzymywać sesji dla każdego użytkownika (co może być dużym obciążeniem, gdy masz wiele sesji)
2- JWT są samodzielne i mają roszczenia, które określają na przykład rolę użytkownika oraz to, do czego może uzyskać dostęp i wydane w dniu i dacie wygaśnięcia (po którym JWT nie będzie ważne)
3- Łatwiejsza obsługa w modułach równoważenia obciążenia, a jeśli masz wiele serwerów API, ponieważ nie będziesz musiał udostępniać danych sesji ani konfigurować serwera tak, aby kierował sesję do tego samego serwera, za każdym razem, gdy żądanie z JWT trafi na dowolny serwer, może zostać uwierzytelnione i autoryzowane
4 - Mniejsza presja na twoją bazę danych, jak również nie będziesz musiał stale przechowywać i pobierać identyfikatora sesji i danych dla każdego żądania
5- Nie można manipulować JWT, jeśli użyjesz silnego klucza do podpisania JWT, więc możesz ufać roszczeniom w JWT wysyłanym z żądaniem bez konieczności sprawdzania sesji użytkownika i czy jest on autoryzowany, czy nie , możesz po prostu sprawdzić JWT, a następnie wszystko jest ustawione, aby wiedzieć, kto i co ten użytkownik może zrobić.
Wiele bibliotek zapewnia łatwe sposoby tworzenia i sprawdzania poprawności JWT w większości języków programowania, na przykład: w node.js jedną z najpopularniejszych jest jsonwebtoken
Ponieważ interfejsy API REST zasadniczo mają na celu utrzymanie bezstanowego serwera, dlatego JWT są bardziej zgodne z tą koncepcją, ponieważ każde żądanie jest wysyłane z tokenem autoryzacji, który jest samowystarczalny (JWT), bez konieczności śledzenia sesji użytkownika przez serwer w porównaniu do sesji, które sprawiają, że serwer stanowy, aby zapamiętał użytkownika i jego rolę, jednak sesje są również powszechnie używane i mają swoje zalety, które możesz wyszukać, jeśli chcesz.
Jedną ważną rzeczą do zapamiętania jest to, że musisz bezpiecznie dostarczyć JWT do klienta za pomocą HTTPS i zapisać go w bezpiecznym miejscu (na przykład w lokalnej pamięci masowej).
Możesz dowiedzieć się więcej o JWT z tego linku
źródło
Jeśli chcesz mieć całkowicie zablokowany obszar aplikacji internetowej, do którego dostęp mają tylko administratorzy z Twojej firmy, autoryzacja SSL może być dla Ciebie. Zapewni to, że nikt nie będzie mógł nawiązać połączenia z instancją serwera, jeśli nie ma zainstalowanego autoryzowanego certyfikatu w przeglądarce. W zeszłym tygodniu napisałem artykuł o konfiguracji serwera: Artykuł
Jest to jedna z najbezpieczniejszych konfiguracji, jaką znajdziesz, ponieważ nie dotyczy to nazwy użytkownika / hasła, więc nikt nie może uzyskać dostępu, chyba że jeden z Twoich użytkowników przekaże pliki kluczy potencjalnemu hakerowi.
źródło