Jak przeprowadzić uwierzytelnianie bezstanowe (bez sesji) i bez plików cookie?

107

Bob używa aplikacji internetowej, aby coś osiągnąć. I:

  • Jego przeglądarka jest na diecie, dlatego nie obsługuje plików cookie .
  • Aplikacja internetowa jest popularna, w danym momencie obsługuje wielu użytkowników - musi się dobrze skalować . Tak długo, jak utrzymywanie sesji nałożyłoby ograniczenie na liczbę jednoczesnych połączeń i oczywiście przyniosłoby znaczący spadek wydajności , możemy chcieć mieć system bezsesyjny :)

Kilka ważnych uwag:

  • mamy zabezpieczenia transportu ( HTTPS i jego najlepsi przyjaciele);
  • za zasłonami aplikacja webowa deleguje wiele operacji do usług zewnętrznych , w imieniu bieżącego użytkownika (systemy te rozpoznają Boba jako jednego ze swoich użytkowników) - oznacza to, że musimy przekazać im dane uwierzytelniające Boba .

A teraz, jak uwierzytelniamy Roberta (przy każdym żądaniu)? Jaki byłby rozsądny sposób na wdrożenie czegoś takiego?

  • gra w tenisa z danymi uwierzytelniającymi za pośrednictwem ukrytych pól formularza HTML ... piłka zawiera dane uwierzytelniające ( nazwę użytkownika i hasło ), a dwie rakiety to odpowiednio przeglądarka i aplikacja internetowa. Innymi słowy, możemy przesyłać dane tam iz powrotem za pośrednictwem pól formularzy zamiast plików cookie. Przy każdym żądaniu sieciowym przeglądarka publikuje poświadczenia. Chociaż w przypadku aplikacji jednostronicowej może to wyglądać jak gra w squasha na gumowej ścianie zamiast gry w tenisa , ponieważ formularz sieciowy zawierający dane uwierzytelniające może pozostać żywy przez cały okres istnienia strony internetowej (a serwer zostanie skonfigurowany tak, aby nie oferował z powrotem poświadczeń).
  • przechowywanie nazwy użytkownika i hasła w kontekście strony - zmienne JavaScript itp. Wymagana jedna strona, IMHO.
  • szyfrowane uwierzytelnianie oparte na tokenach. W takim przypadku logowanie spowodowałoby wygenerowanie zaszyfrowanego tokena bezpieczeństwa (nazwa użytkownika + hasło + coś innego). Ten token zostanie przesłany z powrotem klientowi, a nadchodzącym żądaniom będzie towarzyszył token. Czy to ma sens? Mamy już HTTPS ...
  • inne ...
  • ostateczność: nie rób tego, przechowuj dane logowania w sesji! Sesja jest dobra. Z ciasteczkami lub bez.

Czy przychodzi Ci na myśl jakiś problem z siecią / bezpieczeństwem w związku z którymkolwiek z wcześniej opisanych pomysłów? Na przykład,

  • time-out - możemy zachować znacznik czasu wraz z poświadczeniami (znacznik czasu = czas, w którym Bob wprowadził swoje dane uwierzytelniające). Np. Gdy TERAZ - znacznik czasu> próg , możemy odrzucić żądanie.
  • Ochrona przed skryptami między witrynami - nie powinna się w żaden sposób różnić, prawda?

Bardzo dziękuję za poświęcenie czasu na przeczytanie tego :)

turdus-merula
źródło
2
Możesz dołączyć token do każdego adresu URL. ASP.NET ma do tego tryb (starszy). To dowodzi, że może działać.
usr
1
Gdzie są wszyscy? :)
turdus-merula
2
Myślę, że masz całkiem niezłe pojęcie o dostępnych opcjach. Zaufaj swojemu rozumowaniu i zdecyduj sam.
usr
czy wtyczka taka jak Silverlight of Flash jest opcją?
Giu
@usr nie jestem pewien, czy to dobry pomysł, ponieważ haker dostanie się do dzienników serwera internetowego może ukraść twój token i zalogować się do systemu.
GibboK,

Odpowiedzi:

74

Ach, uwielbiam te pytania - utrzymywanie sesji bez sesji.

Widziałem wiele sposobów, aby to zrobić podczas moich okresów podczas oceny aplikacji. Jednym z popularnych sposobów jest wspomniany przez Ciebie sposób gry w tenisa - wysyłanie nazwy użytkownika i hasła w każdym żądaniu uwierzytelnienia użytkownika. Moim zdaniem jest to niebezpieczne, zwłaszcza jeśli aplikacja nie jest pojedynczą stroną. Nie jest też skalowalny, zwłaszcza jeśli chcesz w przyszłości dodać autoryzację do swojej aplikacji oprócz uwierzytelniania (chociaż myślę, że możesz też zbudować coś na podstawie loginów)

Jednym z popularnych, choć nie całkowicie bezstanowych mechanizmów (zakładając, że wykonujesz JavaScript) jest osadzenie sesyjnego pliku cookie w JavaScript. Ochroniarz we mnie krzyczy na to, ale to może zadziałać - każda prośba maX-Authentication-Tokennagłówek lub coś w tym rodzaju, i mapujesz to do bazy danych, magazynu plików w pamięci itp. na zapleczu, aby zweryfikować użytkownika. Ten token może mieć limit czasu o dowolnej określonej godzinie, a jeśli upłynie, użytkownik musi zalogować się ponownie. Jest dość skalowalny - jeśli przechowujesz go w bazie danych, wykonujesz jedną instrukcję SQL i masz prawidłowe indeksy, wykonanie powinno zająć bardzo mało czasu, nawet przy wielu jednoczesnych użytkownikach. Testowanie obciążenia tutaj zdecydowanie by pomogło. Jeśli dobrze przeczytam pytanie, byłby to mechanizm zaszyfrowanego tokena - chociaż zdecydowanie sugerowałbym użycie kryptograficznie losowego tokena, powiedzmy 32 znaków, zamiast użycia kombinacji nazwa użytkownika + hasło + cokolwiek innego - w ten sposób pozostaje nieprzewidywalny, ale nadal możesz go powiązać z identyfikatorem użytkownika lub czymś podobnym.

Niezależnie od tego, z czego ostatecznie korzystasz, upewnij się, że zostało ono bezpiecznie wysłane. HTTPS chroni Cię przez cały kabel, ale nie chroni Cię, jeśli wyciekniesz token sesji za pośrednictwem adresu URL (lub, co gorsza, poświadczeń za pośrednictwem adresu URL). Zalecałbym użycie nagłówka lub, jeśli jest to niewykonalne, wysyłanie tokena za pośrednictwem żądania POST za każdym razem (oznaczałoby to ukryte pole formularza w przeglądarce użytkownika). To drugie podejście polegające na użyciu żądania POST powinno korzystać z zabezpieczeń CSRF, po prostu na wypadek, chociaż podejrzewam, że użycie samego tokena może być pewnego rodzaju obroną CSRF.

Wreszcie, upewnij się, że masz w zapleczu mechanizm do usuwania wygasłych tokenów. W przeszłości było to zmorą wielu aplikacji - szybko rosnącej bazy danych tokenów uwierzytelniających, która wydaje się nigdy nie zniknąć. Jeśli potrzebujesz obsługi logowania wielu użytkowników, upewnij się, że ograniczasz liczbę lub masz krótszy limit czasu na każdy token. Jak powiedziałem wcześniej, odpowiedzią na to może być testowanie obciążenia.

Są inne problemy związane z bezpieczeństwem, które przychodzą mi do głowy, ale są one zbyt szerokie, aby można je było rozwiązać na tym etapie - jeśli weźmiesz pod uwagę wszystkie przypadki użycia (i nadużyć), prawdopodobnie powinieneś być w stanie wykonać dość dobrą implementację ten system.

Karthik Rangarajan
źródło
Nie możesz zrobić tego, co robi platforma odtwarzania i wysłać podpisany plik cookie do użytkownika? Czy następnie ten plik cookie jest wysyłany z powrotem na serwer przy każdym kolejnym żądaniu?
j będzie
8
> Jego przeglądarka jest na diecie, dlatego nie obsługuje plików cookie.
Karthik Rangarajan
4
Czy któraś z tych sugestii jest faktycznie bezpaństwowa / sesyjna ? Spośród pięciu głównych akapitów (stan z 19.12.2013 r.): Nr 1 jest wprowadzeniem, nr 2 proponuje dodatkowe sesje o smaku Web2.0 ™, nr 3 to tylko upomnienia, nr 4 omawia konsekwencje stanowości , a numer 5 to niejasne zakończenie ... jak to zostało zaakceptowane? W najlepszym przypadku jest to informacja styczna!
JamesTheAwesomeDude
1

O opcji logowania - myślę, że zazwyczaj chcesz obsługiwać sesje również dla gości.

Tak więc, jeśli chcesz wymusić logowanie, opcja zaszyfrowanego tokena może być dobra. To może być jakoś dobre również na sesję gościnną. W innym kierunku połączyłbym między dołączeniem tokena do adresu URL i opcją tenisa.

Zwróć uwagę, że wysyłanie danych logowania tylko w adresie URL może być niebezpieczne. Na przykład możesz ujawnić token za pośrednictwem nagłówka HTTP referer lub nawet przez osobę, która po prostu sprawdza Twój ruch lub obserwuje Twój komputer.

Inną rzeczą, nawet jeśli możesz używać plików cookie, polecam dodanie losowego tokena lub losowego weryfikatora, aby chronić się przed atakami Cross Site Request Forgery (CSRF).

Gari BN
źródło
3
Sesja to stan przechowywany na serwerze. Pytanie dotyczy uwierzytelniania bezstanowego.
Kwebble