Czy używanie sesji w RESTful API naprawdę narusza RESTfulness? Widziałem wiele opinii zmierzających w obu kierunkach, ale nie jestem przekonany, że sesje są bez RESTless . Z mojego punktu widzenia:
- Uwierzytelnianie nie jest zabronione dla RESTfulness (w przeciwnym razie użycie usług RESTful byłoby niewielkie)
- uwierzytelnianie odbywa się poprzez wysłanie tokena uwierzytelniającego w żądaniu, zwykle w nagłówku
- ten token uwierzytelniający musi zostać w jakiś sposób uzyskany i może zostać odwołany, w takim przypadku należy go odnowić
- token uwierzytelniający musi zostać zweryfikowany przez serwer (w przeciwnym razie nie byłby to uwierzytelnienie)
Jak więc sesje to naruszają?
- sesje po stronie klienta są realizowane przy użyciu plików cookie
- pliki cookie to po prostu dodatkowy nagłówek HTTP
- sesyjny plik cookie można uzyskać i odwołać w dowolnym momencie
- W razie potrzeby sesyjne pliki cookie mogą mieć nieskończony czas życia
- identyfikator sesji (token uwierzytelnienia) jest sprawdzany po stronie serwera
W związku z tym dla klienta plik cookie sesji jest dokładnie taki sam, jak każdy inny mechanizm uwierzytelniania oparty na nagłówku HTTP, z tym wyjątkiem, że używa Cookie
nagłówka zamiast Authorization
lub innego zastrzeżonego nagłówka. Jeśli po stronie serwera nie była dołączona żadna sesja, dlaczego miałoby to mieć znaczenie? Implementacja po stronie serwera nie musi dotyczyć klienta, o ile serwer działa w trybie RESTful. Jako takie same pliki cookie nie powinny tworzyć interfejsu API RESTless , a sesje są po prostu plikami cookie dla klienta.
Czy moje założenia są błędne? Co powoduje, że sesyjne pliki cookie RESTless ?
Odpowiedzi:
Najpierw zdefiniujmy niektóre terminy:
Spokojny:
według wikipedii .
ograniczenie bezstanowe:
zgodnie z rozprawą Fieldinga .
Tak więc sesje po stronie serwera naruszają bezstanowe ograniczenie REST, a więc i RESTfulness.
Poprzez sesyjne pliki cookie przechowujesz stan klienta na serwerze, dzięki czemu Twoje zapytanie ma kontekst. Spróbujmy dodać do systemu moduł równoważenia obciążenia i inną instancję usługi. W takim przypadku musisz udostępnić sesje między instancjami usługi. Taki system jest trudny do utrzymania i rozbudowy, więc źle się skaluje ...
Moim zdaniem nie ma nic złego w plikach cookie. Technologia plików cookie to mechanizm przechowywania po stronie klienta, w którym przechowywane dane są automatycznie dołączane do nagłówków plików cookie przy każdym żądaniu. Nie znam ograniczenia REST, które ma problem z tego rodzaju technologią. Tak więc nie ma problemu z samą technologią, problemem jest jej użycie. Fielding napisał podrozdział o tym, dlaczego uważa, że pliki cookie HTTP są złe.
Twój punkt widzenia był dość solidny. Jedynym problemem była koncepcja utworzenia tokena uwierzytelniającego na serwerze. Nie potrzebujesz tej części. Potrzebne jest przechowywanie nazwy użytkownika i hasła na kliencie i wysyłanie go przy każdym żądaniu. Nie potrzebujesz więcej do zrobienia niż podstawowe uwierzytelnianie HTTP i szyfrowane połączenie:
Prawdopodobnie potrzebujesz pamięci podręcznej uwierzytelniania w pamięci po stronie serwera, aby przyspieszyć, ponieważ musisz uwierzytelniać każde żądanie.
Teraz działa to całkiem dobrze przez zaufanych klientów napisanych przez ciebie, ale co z klientami zewnętrznymi? Nie mogą mieć nazwy użytkownika i hasła oraz wszystkich uprawnień użytkowników. Musisz więc oddzielnie przechowywać, jakie uprawnienia może mieć klient zewnętrzny dla konkretnego użytkownika. Dzięki temu programiści klientów mogą zarejestrować swoich klientów zewnętrznych i uzyskać unikalny klucz API, a użytkownicy mogą zezwolić klientom zewnętrznym na dostęp do części swoich uprawnień. Podobnie jak czytanie imienia i adresu e-mail lub lista znajomych itp. ... Po zezwoleniu klientowi zewnętrznemu serwer wygeneruje token dostępu. Te tokeny dostępu mogą być używane przez klienta zewnętrznego do uzyskiwania dostępu do uprawnień przyznanych przez użytkownika, w następujący sposób:
Klient zewnętrzny może więc uzyskać token dostępu od zaufanego klienta (lub bezpośrednio od użytkownika). Następnie może wysłać prawidłowe żądanie z kluczem API i tokenem dostępu. Jest to najbardziej podstawowy mechanizm autoryzacji innej firmy. Możesz przeczytać więcej o szczegółach implementacji w dokumentacji każdego zewnętrznego systemu uwierzytelniania, np. OAuth. Oczywiście może to być bardziej złożone i bezpieczniejsze, na przykład możesz podpisać szczegóły każdego pojedynczego żądania po stronie serwera i wysłać podpis wraz z żądaniem itd. Rzeczywiste rozwiązanie zależy od potrzeb Twojej aplikacji.
źródło
Po pierwsze, REST nie jest religią i do takich nie należy podchodzić. Chociaż usługi RESTful mają zalety, powinieneś podążać za zasadami REST tylko w takim zakresie, w jakim ma to sens dla twojej aplikacji.
To powiedziawszy, uwierzytelnianie i stan po stronie klienta nie naruszają zasad REST. Podczas gdy REST wymaga, aby przejścia między stanami były bezstanowe, dotyczy to samego serwera. W centrum całego REST są dokumenty. Idea bezpaństwowości polega na tym, że SERWER jest bezpaństwowcem, a nie klientem. Każdy klient wysyłający identyczne żądanie (takie same nagłówki, pliki cookie, identyfikator URI itp.) Należy zabrać w to samo miejsce w aplikacji. Jeśli witryna zachowa bieżącą lokalizację użytkownika i zarządza nawigacją poprzez aktualizację tej zmiennej nawigacyjnej po stronie serwera, REST zostanie naruszony. Inny klient z identycznymi informacjami o żądaniach zostałby zabrany do innej lokalizacji w zależności od stanu po stronie serwera.
Usługi sieciowe Google są fantastycznym przykładem systemu RESTful. Wymagają one nagłówka uwierzytelniającego z kluczem uwierzytelniającym użytkownika, który należy przekazać na każde żądanie. Nieznacznie narusza to zasady REST, ponieważ serwer śledzi stan klucza uwierzytelniającego. Stan tego klucza musi zostać zachowany i ma on jakąś datę / godzinę wygaśnięcia, po której nie udziela już dostępu. Jednak, jak wspomniałem na początku mojego postu, należy poświęcić się, aby aplikacja mogła faktycznie działać. To powiedziawszy, tokeny uwierzytelniające muszą być przechowywane w sposób, który pozwoli wszystkim możliwym klientom na dalsze udzielanie dostępu w czasie ich obowiązywania. Jeśli jeden serwer zarządza stanem klucza uwierzytelniania do tego stopnia, że inny serwer z równoważeniem obciążenia nie może przejąć spełniania żądań na podstawie tego klucza, zacząłeś naprawdę łamać zasady REST. Usługi Google zapewniają, że w każdej chwili możesz pobrać token uwierzytelniania, którego używałeś w telefonie, z serwerem równoważenia obciążenia A i trafić na serwer równoważenia obciążenia B z pulpitu i nadal mieć dostęp do systemu i być skierowany do tych samych zasobów, jeśli wnioski były identyczne.
Wszystko sprowadza się do tego, że musisz upewnić się, że tokeny uwierzytelniające są sprawdzane pod kątem pewnego rodzaju bazy danych (baza danych, pamięć podręczna, cokolwiek innego), aby zapewnić zachowanie jak największej liczby właściwości REST.
Mam nadzieję, że to wszystko miało sens. Powinieneś również sprawdzić sekcję Ograniczenia artykułu w Wikipedii na temat Reprezentatywnego transferu stanu, jeśli jeszcze tego nie zrobiłeś. Jest to szczególnie pouczające w odniesieniu do argumentów REST i dlaczego.
źródło
Pliki cookie nie służą do uwierzytelniania. Po co wymyślać koło? HTTP ma dobrze zaprojektowane mechanizmy uwierzytelniania. Jeśli używamy plików cookie, popadamy w użycie protokołu HTTP tylko jako protokołu transportowego, dlatego musimy stworzyć własny system sygnalizacyjny, na przykład, aby poinformować użytkowników, że podali nieprawidłowe uwierzytelnianie (użycie HTTP 401 byłoby nieprawidłowe, ponieważ prawdopodobnie nie dostarczanie
Www-Authenticate
do klienta, jak wymagają specyfikacje HTTP :)). Należy również zauważyć, żeSet-Cookie
jest to tylko zalecenie dla klienta. Jego zawartość może zostać zapisana (lub nie) (na przykład, jeśli pliki cookie są wyłączone), aAuthorization
nagłówek jest wysyłany automatycznie na każde żądanie.Inną kwestią jest to, że aby uzyskać cookie autoryzacji, prawdopodobnie najpierw chcesz podać swoje dane uwierzytelniające? Jeśli tak, to czy nie byłby to RESTless? Prosty przykład:
GET /a
bez pliku cookiePOST /auth
Set-Cookie
GET /a
z ciasteczkiem. Ale czyGET /a
w tym przypadku zachowuje się idempotentnie?Podsumowując, uważam, że jeśli uzyskamy dostęp do jakiegoś zasobu i musimy się uwierzytelnić, to musimy uwierzytelnić się na tym samym zasobie , nigdzie indziej.
źródło
Authorization: Basic
lubDigest
. Jeśli chcesz zrobić coś bardziej zaawansowanego niż uwierzytelnianie podstawowe lub podsumowanie (i powinieneś) w kontekście przeglądarki, potrzebujesz czegoś innego niżAuthorization
nagłówek.GET /a
bez pliku cookie i z plikiem cookie są wyraźnie dwa różne żądania i dopuszczalne jest, aby zachowywały się inaczej.GET /a
nagłówek uwierzytelnienia jest również taki sam jakGET /a
bez nagłówka uwierzytelnienia, co czyni go równie bezużytecznym dla REST. Jeśli zamierzasz traktować jeden nagłówek http inaczej niż inny, to przynajmniej rozwiążesz ten problem.W rzeczywistości RESTfulness dotyczy tylko ZASOBÓW, jak wskazuje uniwersalny identyfikator zasobu. Mówienie nawet o nagłówkach, plikach cookie itp. W odniesieniu do REST nie jest tak naprawdę właściwe. REST może działać na dowolnym protokole, nawet jeśli dzieje się to rutynowo przez HTTP.
Główny determinant jest następujący: jeśli wysyłasz wywołanie REST, które jest identyfikatorem URI, to kiedy wywołanie zakończy się powodzeniem na serwerze, czy identyfikator URI zwraca tę samą treść, zakładając, że nie wykonano żadnych przejść (PUT, POST, DELETE) ? Ten test wyklucza zwracanie błędów lub żądań uwierzytelnienia, ponieważ w takim przypadku żądanie nie dotarło jeszcze do serwera, co oznacza serwlet lub aplikację, która zwróci dokument odpowiadający podanemu identyfikatorowi URI.
Podobnie, w przypadku POST lub PUT, czy możesz wysłać dany URI / ładunek i niezależnie od tego, ile razy wysyłasz wiadomość, zawsze będzie aktualizować te same dane, aby kolejne GET zwróciły spójny wynik?
REST dotyczy danych aplikacji, a nie informacji niskiego poziomu wymaganych do przeniesienia tych danych.
W poniższym wpisie na blogu Roy Fielding podał miłe podsumowanie całego pomysłu REST:
http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/5841
„System RESTful przechodzi od jednego stanu ustalonego do następnego, a każdy taki stan ustalony jest zarówno potencjalnym stanem początkowym, jak i potencjalnym stanem końcowym. Tzn. System RESTful to nieznana liczba komponentów spełniających prosty zestaw reguły takie, że zawsze znajdują się w stanie REST lub przechodzą z jednego stanu RESTful do innego stanu RESTful Każdy stan może być w pełni zrozumiany przez reprezentację (-y) w nim zawartą oraz zestaw zapewnianych przez niego przejść, przy czym przejścia są ograniczone do jednolitego zestaw działań, które powinny być zrozumiałe. System może być złożonym diagramem stanów, ale każdy klient użytkownika może widzieć tylko jeden stan na raz (bieżący stan ustalony), a zatem każdy stan jest prosty i może być analizowany niezależnie. użytkownik OTOH może w dowolnym momencie tworzyć własne przejścia (np. wpisać adres URL, wybrać zakładkę,otwórz edytor itp.). ”
Przechodząc do kwestii uwierzytelnienia, niezależnie od tego, czy odbywa się to za pomocą plików cookie, czy nagłówków, tak długo, jak informacje te nie są częścią ładunku URI i POST, tak naprawdę w ogóle nie ma to nic wspólnego z REST. W związku z tym, że jesteśmy bezpaństwowcami, mówimy tylko o danych aplikacji.
Na przykład, gdy użytkownik wprowadza dane do ekranu GUI, klient śledzi, które pola zostały wprowadzone, a które nie, żadnych wymaganych brakujących pól itp. To jest KONTEKST KLIENTA i nie należy go wysyłać ani śledzić przez serwer. Do serwera wysyłany jest pełny zestaw pól, które należy zmodyfikować w zasobie IDENTYFIKOWANYM (za pomocą identyfikatora URI), aby w tym zasobie nastąpiło przejście z jednego stanu RESTful do innego.
Tak więc klient śledzi to, co robi użytkownik, i wysyła tylko logicznie kompletne przejścia stanu na serwer.
źródło
Transakcja HTTP, podstawowe uwierzytelnianie dostępu, nie jest odpowiednie dla RBAC, ponieważ podstawowe uwierzytelnianie dostępu wykorzystuje zaszyfrowaną nazwę użytkownika: hasło za każdym razem do identyfikacji, podczas gdy w RBAC potrzebna jest rola, którą użytkownik chce użyć dla określonego połączenia. RBAC nie sprawdza uprawnień do nazwy użytkownika, ale do ról.
Możesz spróbować połączyć w następujący sposób: nazwa_użytkownikaRola: hasło, ale jest to zła praktyka, a także nieefektywna, ponieważ gdy użytkownik ma więcej ról, silnik uwierzytelniający musiałby przetestować wszystkie role w konkatenacji i to każde ponowne wywołanie. To zniszczyłoby jedną z największych technicznych zalet RBAC, a mianowicie bardzo szybki test autoryzacyjny.
Tak więc tego problemu nie można rozwiązać za pomocą podstawowego uwierzytelnienia dostępu.
Aby rozwiązać ten problem, utrzymanie sesji jest konieczne i wydaje się, zgodnie z niektórymi odpowiedziami, sprzeczne z REST.
Właśnie to podoba mi się w odpowiedzi, że REST nie powinno być traktowane jako religia. W skomplikowanych przypadkach biznesowych, na przykład w opiece zdrowotnej, RBAC jest absolutnie powszechny i konieczny. Szkoda byłoby, gdyby nie mogli używać REST, ponieważ wszyscy projektanci narzędzi REST traktowali REST jako religię.
Dla mnie nie ma wielu sposobów na utrzymanie sesji przez HTTP. Można używać plików cookie z sessionId lub nagłówka z sessionId.
Jeśli ktoś ma inny pomysł, chętnie go usłyszę.
źródło
myślę, że token musi zawierać wszystkie potrzebne informacje zakodowane w nim, co powoduje uwierzytelnienie poprzez sprawdzenie tokena i odkodowanie informacji https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
źródło
źródło