Jakiego kodu stanu http należy użyć, aby poinformować klienta o przekroczeniu limitu czasu sesji?

80

Na stronie internetowej używa menedżera połączeń / źródła danych YUI do wysyłania żądań AJAX do serwera, jeśli sesja (która zawiera informacje o tym, czy użytkownik został uwierzytelniony) już przekroczyła limit czasu, te odpowiedzi AJAX, które mogą być przeglądane tylko przez uwierzytelnionego użytkownicy powinni zwrócić kod statusu http, informując klienta, że ​​sesja już przekroczyła limit czasu, a następnie klient albo po prostu przekierowuje go na stronę logowania, albo pyta, czy chce przedłużyć sesję.

Moje pytanie jest takie, że w tej sytuacji, jaki kod statusu http jest najbardziej odpowiedni do poinformowania klienta o przekroczeniu limitu czasu sesji?

Lista kodów statusu HTTP z wiki

bobo
źródło
Czy chcesz ostrzec użytkownika, że ​​sesja wkrótce wygaśnie, aby mógł zrobić coś, aby ją odnowić? W takim przypadku musiałby być obsługiwany przez licznik czasu w JavaScript, który wyłącza się przed upływem limitu czasu sesji na serwerze. Zanim kod statusu zostanie wysłany przez serwer, już wygasł. Licznik czasu byłby również potrzebny, gdybyś automatycznie przekierowywał ich na inną stronę, jeśli pozostawili stronę bezczynną.
Jason
8
Dlaczego, oczywiście 418! Niski i tęgi ...
Tim Post
Vaadin używa 410 Gone, ale ponieważ jest zapisywany w pamięci podręcznej przez przeglądarkę, nie polecam go
sreg

Odpowiedzi:

66

Najlepsze, co mogę zasugerować, to kod stanu HTTP 401 z nagłówkiem WWW-Authenticate.

Problem z żądaniami 403 polega na tym, że RFC 2616 stwierdza, że ​​„Autoryzacja nie pomoże i żądanie NIE POWINNO być powtarzane”. (tj. nie ma znaczenia, czy jesteś uwierzytelniony, czy nie, nigdy nie uzyskasz dostępu do tego zasobu).

Problem z żądaniami 401 polega na tym, że „MUSZĄ zawierać pole nagłówka WWW-Authenticate”. Jak ktoś zauważył , użycie niestandardowej wartości w nagłówku WWW-Authenticate nie wydaje się naruszać specyfikacji.

Nie widzę żadnego powodu w RFC 2617, dlaczego status HTTP 401 w połączeniu z niestandardowym nagłówkiem WWW-Authenticate, takim jak ten, nie byłby w porządku:

WWW-Authenticate: MyAuthScheme realm="http://example.com"

OAuth Spec rzeczywiście wydaje się zrobić tylko to, jak oni polecam (choć mają moim zdaniem dziwna interpretacja RFC):

WWW-Authenticate: OAuth realm="http://server.example.com/"

Wydaje się, że nie jest to specjalnie SANKCJONOWANE przez RFC, ale tak naprawdę nie widzę, że jest to zabronione (nie wydaje się kolidować z żadnym warunkiem MUSI lub NIE WOLNO, POWINIEN lub NIE POWINIEN).

Chciałbym, żeby istniał bardziej szczegółowy kod stanu HTTP dla limitów czasu i rzeczy, takich jak tokeny CSRF, które są nieprawidłowe, więc było to wyraźniejsze.

Iain Collins
źródło
34

Poleciłbym HTTP 401.

Podczas gdy 403 zasadniczo mówi: „Nie wolno ci odejść i nie wracaj”, 401 mówi: „Nie wiemy, czy masz pozwolenie, czy nie, ponieważ nie przyniosłeś swojego dowodu tożsamości. weź go i spróbuj ponownie ”.

Porównaj definicje Wikipedii :

HTTP 403 - żądanie było żądaniem prawnym, ale serwer odmawia odpowiedzi.

HTTP 401 - podobny do 403 zabroniony, ale specjalnie do użytku, gdy uwierzytelnianie jest możliwe, ale nie powiodło się lub nie zostało jeszcze dostarczone.

Jonathon Hill
źródło
3
401 ma służyć do uwierzytelniania HTTP . RFC 2616 mówi response MUST include a WWW-Authenticate header field. Dlatego wysyłanie tego kodu bez pola nagłówka WWW-Authenticate jest błędne .
Toxalot
19

A co z 419 - to nie jest standardowe, ale opis na Wikipedii wydaje się pasować:

419 Limit czasu uwierzytelniania

Nie jest częścią standardu HTTP, 419 Authentication Timeout oznacza, że ​​poprzednio ważne uwierzytelnienie wygasło. Jest używany jako alternatywa dla 401 Nieautoryzowany w celu odróżnienia od inaczej uwierzytelnionych klientów, którym odmawia się dostępu do określonych zasobów serwera.

John Reichert
źródło
14
Jakiś pomysł, skąd to się bierze (poza Wikipedią)? Jeśli nie ma tego w oficjalnym RFC, kto to zdefiniował?
anaximander
5
Wydaje się, że został również usunięty z tej strony wiki
Salem Ouerdani,
Nie jest to część specyfikacji, ani dostępna w Javie HttpServletResponse@John, jeśli znasz inne wiarygodne źródło, lepiej się do niego odwołać.
Vishrant,
Wydaje się, że jestem używany tylko w PHP Laravel
TroySteven
12

Uważam, że odpowiednim kodem będzie 403 / zabronione. Nie ma żadnych, które są bezpośrednio związane z sesjami.

Jason
źródło
1
Absolutnie to jest poprawna odpowiedź. Ponieważ sesja wygasła, żądanie jest zabronione, więc jest to najlepszy wybór.
marcc
3
403 mówi klientowi (zasadniczo) „Nie rób tego ponownie, chyba że zmodyfikujesz żądanie”, ale jeśli sesja została ustanowiona, żadna modyfikacja nie byłaby potrzebna. Ponadto w większości przypadków nie możesz nic zrobić z (bieżącą) prośbą o ponowne nawiązanie sesji.
Tim Post
1
Dokładnie! Myślę, że 401 byłoby lepsze, ale wymaga uwierzytelnienia HTTP. Myślę, że wymaga to nowego statusu na wzór 401 + 303 (więc oczywiście 704), co oznacza „Brak autoryzacji, zobacz inne, aby uzyskać autoryzację”. Oprócz tego, że jest bardziej poprawny semantycznie, może to być również rozwiązanie HTTP do przekierowania trampoliny, po prostu „idź tutaj, a kiedy wrócisz, spróbujemy ponownie”, aby strona logowania mogła być agnostyczna w odniesieniu do Miejsce docelowe.
Anthony
5
Nie mogę się z tym zgodzić, RFC 2616 wyraźnie stwierdza, że ​​żądania powodujące odpowiedź 403 „NIE POWINNY być powtarzane” przez klienta i że „autoryzacja nie pomoże”.
Iain Collins,
5
authorization will not help- Rozumiem, że uwierzytelnianie HTTP nie pomoże. Który jest poprawny. Wysłanie nagłówka Authorization niczego nie zmieni. Ani 401, ani 403 nie są idealne, ale myślę, że 403 jest lepsze niż 401. 401 jest błędne w przypadku limitu czasu sesji, ponieważ RFC 2616 wyraźnie stwierdza client MAY repeat the request with a suitable Authorization header field. Ale w tym przypadku klient NIE POWINIEN powtarzać żądania (przynajmniej nie bez etapu przejściowego). Niestety nie możemy przekazać tej drugiej części kodu statusu.
toxalot
11

Prawda jest taka, że ​​nie ma standardowego kodu statusu HTTP określającego limit czasu sesji. Sesje są implementowane w warstwie aplikacji, a nie w warstwie transportowej HTTP.

Istnieje niestandardowy kod stanu, którego Microsoft używał do przekroczenia limitu czasu sesji: 599 lub po prostu utwórz własny kod stanu z zakresu 5xx.

Z Wiki kodów stanu:

599 Błąd przekroczenia limitu czasu połączenia sieciowego (nieznany) Ten kod stanu nie jest określony w żadnym dokumencie RFC, ale jest używany przez serwery proxy HTTP firmy Microsoft do sygnalizowania klientowi znajdującemu się przed serwerem proxy limitu czasu połączenia sieciowego za serwerem proxy.

Używam niestandardowego kodu stanu 599 do przekroczenia limitu czasu sesji, a następnie sprawdzam go w odpowiedzi AJAX.

Dermot Doherty
źródło
3
Limit czasu połączenia sieciowego bardzo różni się od limitu czasu sesji. Jeśli zamierzasz użyć kodu z rozszerzenia Microsoftu, dlaczego nie użyć 440 Login Timeout (Microsoft)zgodnie z odpowiedzią Faisal
Mq
Ta strona Wikipedii o 599 była błędna i nie zawierała żadnych cytatów. Najwyraźniej zwykł mówić, że serwery proxy Microsoftu zwiększają 599 limitów czasu sieci, ale nie mogłem znaleźć na to żadnych dowodów.
Gareth Davidson
11

Zgodnie z linkiem Wikipedii do kodów stanu HTTP podanych powyżej przez Bobo:

440 Login Timeout (Microsoft)

    A Microsoft extension. Indicates that your session has expired.
Faisal Mq
źródło
Zwróć
Podoba mi się to rozwiązanie dla środowisk ASP.NET.
TroySteven
9

Kiedy publikujesz łącze, w tym łączu znalazłem kod statusu HTTP 440 . możesz użyć 440 kodu statusu HTTP dla wygasłej sesji.

440 Limit czasu logowania

 The client's session has expired and must log in again.

401 Nieautoryzowany, którego możemy użyć, gdy dane logowania użytkownika są nieprawidłowe. lub token uwierzytelniania przekazany w nagłówku jest nieprawidłowy.

403 Zabronione, możemy tego użyć, gdy użytkownik nie ma określonych uprawnień do żądanego zasobu.

Więc moim zdaniem powinniśmy użyć 440 Limit czasu logowania .

Vinay Pandya
źródło
2

Technicznie rzecz biorąc, zaakceptowana odpowiedź jest oczywiście poprawna: jeśli już wiesz na pewno, że żądanie nie powiedzie się i pytasz, który kod błędu zwrócić, to właściwy jest HTTP 401 „Unauthorized (Unauthenticated)”, w celu wezwania do ponownego uwierzytelnienia.

Ale przede wszystkim zadaj sobie pytanie: czy nie powinieneś odrzucić prośby?

Weź pod uwagę, że użytkownik może po prostu odwiedzać publiczną stronę Twojej witryny, w którym to przypadku będziesz uderzać go po twarzy komunikatem „Nieautoryzowany!” wiadomości i wymagając od nich ponownego uwierzytelnienia, aby zobaczyć stronę, którą normalnie mogliby zobaczyć bez uwierzytelniania. To nie fajne.

Radzę zignorować fakt, że token sesji jest nieznany i po prostu przystąpić do wygenerowania nowego tokenu sesji i utworzenia dla niego nowej sesji. Początkowy stan sesji będzie oczywiście „jeszcze nie uwierzytelniony”, więc jeśli użytkownik próbuje uzyskać dostęp do strony niepublicznej, strona zobaczy, że otrzyma komunikat HTTP 401 „Nieautoryzowany (nieuwierzytelniony)” ”i musi zostać uwierzytelniony. Ale jeśli użytkownik wyląduje na stronie publicznej, nie zauważy niczego innego.

Mike Nakis
źródło
0

Użyłbym odpowiedzi przekierowania 302 z nagłówkiem „Location” kierującym do ścieżki zasobu takiej jak „/ auth-required”

Klient może skierować ścieżkę zasobu do modalu za pomocą formularza logowania / hasła, unikając przenoszenia użytkownika na inną stronę.

pinei
źródło
-3

W przypadku żądań innych niż Ajax używam przekierowania 302.

W przypadku żądań Ajax używam 200 dla znanych błędów. W ten sposób mogę skorzystać z obiektu danych. Uważam, że obiekt danych jest łatwiejszy w obsłudze niż analizowanie jqXHR w celu uzyskania informacji. A potem nie muszę się martwić, jaki kod statusu HTTP próbować zmienić w mojej sytuacji.

Przykład jQuery:

$.ajax({
    //send data to server
})
.done(function(data, textStatus, jqXHR) {
    if (data.success) {
        //then process return data
    }
    else {
        //get error type or message from data object
        //could use custom error codes
    }
})
.fail(function(jqXHR, textStatus, errorThrown) {
    //handle unknown errors
});
toksalot
źródło
6
Brak chęci analizowania odpowiedzi nie jest dobrym powodem do odstępstwa od specyfikacji HTTP, zwłaszcza gdy można po prostu JSON.parse (responseText).
David Nelson
Nie sądzę, aby użycie kodu odpowiedzi 200 różniło się od specyfikacji HTTP w tym przypadku, ponieważ żądanie zostało technicznie pomyślne w warstwie transportowej. Dla mnie limity czasu sesji są podobne do błędów formularza, w przypadku których zwracam przyjazny dla użytkownika komunikat o błędzie. Rozbieżności wyrażone w odpowiedziach na to pytanie wyraźnie wskazują, że specyfikacja HTTP nie zawiera akceptowanego w branży kodu odpowiedzi dla limitów czasu sesji. Jak można odejść od specyfikacji, która nie istnieje?
toxalot
-4

Kod 408. „Limit czasu żądania” wydaje się doskonały - wyjaśnia to RFC 2616

Klient nie przedstawił żądania w czasie, gdy serwer był przygotowany do oczekiwania.

tj. dokładnie „przerwa”, tak jak potrzebujesz!

Alex Martelli
źródło
4
Ach, ale spójrz na resztę definicji: „Klient może powtórzyć żądanie bez modyfikacji w dowolnym późniejszym czasie”. „Bez modyfikacji” oznaczałoby, że nowa sesja mogłaby zostać utworzona po prostu przez ponowne załadowanie / odświeżenie żądania. W większości przypadków, gdy używane jest uwierzytelnianie, użytkownik musiałby najpierw zalogować się ponownie.
AJ.
@AJ, oczywiście powtarzające się żądanie może skutkować wyzwaniem uwierzytelniającym (kod HTTP 401) - w specyfikacjach HTTP nie widać niczego, co by tego zabraniało , czy możesz coś wskazać?
Alex Martelli
5
408 mówi klientowi, że powinien po prostu spróbować ponownie przesłać żądanie w takiej postaci, w jakiej jest, co oczywiście nie może działać, jeśli upłynął limit czasu sesji.
Tim Post
4
408 to limit czasu żądania, a nie limit czasu sesji. Oznacza to, że gniazdo zostało założone, ale trwało to zbyt długo. Ta strona robi dobrą robotę, wyjaśniając to: checkupdown.com/status/E408.html
Brad Cupit