Jaki jest prawidłowy kod stanu HTTP podczas przekierowywania do strony logowania?

137

Kiedy użytkownik nie jest zalogowany i próbuje uzyskać dostęp do strony wymagającej logowania, jaki jest poprawny kod stanu HTTP dla przekierowania do strony logowania?

Pytam, ponieważ żaden z kodów odpowiedzi 3xx określonych przez W3C nie wydaje się spełniać wymagań:

10.3.1 300 wielokrotnych wyborów

Żądany zasób odpowiada dowolnemu z zestawu reprezentacji, z których każda ma swoją własną, określoną lokalizację, i dostarczane są informacje negocjacyjne oparte na agentach (sekcja 12), aby użytkownik (lub agent użytkownika) mógł wybrać preferowaną reprezentację i przekierować jej żądanie do tej lokalizacji.

O ile nie było to żądanie HEAD, odpowiedź POWINNA zawierać encję zawierającą listę charakterystyk zasobów i lokalizacji, z których użytkownik lub agent użytkownika może wybrać najbardziej odpowiednią. Format jednostki jest określony przez typ nośnika podany w polu nagłówka Content-Type. W zależności od formatu i możliwości

agent użytkownika, wybór najwłaściwszego wyboru MOŻE być wykonany automatycznie. Jednak ta specyfikacja nie definiuje żadnego standardu takiego automatycznego wyboru.

Jeśli serwer ma preferowany wybór reprezentacji, POWINIEN dołączyć określony identyfikator URI dla tej reprezentacji w polu Lokalizacja; agenty użytkownika MOGĄ używać wartości pola Lokalizacja do automatycznego przekierowania. Ta odpowiedź może być buforowana, chyba że wskazano inaczej.

10.3.2 301 Przeniesiono na stałe

Do żądanego zasobu został przypisany nowy stały identyfikator URI, a wszelkie przyszłe odwołania do tego zasobu POWINNY używać jednego ze zwróconych identyfikatorów URI. Klienci z możliwością edycji linków powinni automatycznie ponownie łączyć odniesienia do URI żądania z jednym lub większą liczbą nowych odniesień zwróconych przez serwer, jeśli to możliwe. Ta odpowiedź może być buforowana, chyba że wskazano inaczej.

Nowy stały URI POWINIEN być podany w polu Location odpowiedzi. O ile metoda żądania nie była HEAD, jednostka odpowiedzi POWINNA zawierać krótką notatkę hipertekstową z hiperłączem do nowych identyfikatorów URI.

Jeśli kod stanu 301 zostanie odebrany w odpowiedzi na żądanie inne niż GET lub HEAD, agent użytkownika NIE MOŻE automatycznie przekierowywać żądania, chyba że zostanie to potwierdzone przez użytkownika, ponieważ może to zmienić warunki, na jakich żądanie zostało wysłane.

  Note: When automatically redirecting a POST request after
  receiving a 301 status code, some existing HTTP/1.0 user agents
  will erroneously change it into a GET request.

10.3.3 302 Znaleziono

Żądany zasób znajduje się tymczasowo pod innym identyfikatorem URI. Ponieważ przekierowanie może być czasami zmieniane, klient POWINIEN nadal używać identyfikatora URI żądania dla przyszłych żądań. Ta odpowiedź może zostać zapisana w pamięci podręcznej tylko wtedy, gdy jest to wskazane w polu nagłówka Cache-Control lub Expires.

Tymczasowy URI POWINIEN być podany w polu Location odpowiedzi. O ile metoda żądania nie była HEAD, jednostka odpowiedzi POWINNA zawierać krótką notatkę hipertekstową z hiperłączem do nowych URI.

Jeśli kod statusu 302 zostanie odebrany w odpowiedzi na żądanie inne niż GET lub HEAD, agent użytkownika NIE MOŻE automatycznie przekierowywać żądania, chyba że zostanie to potwierdzone przez użytkownika, ponieważ może to zmienić warunki, na jakich żądanie zostało wysłane.

  Note: RFC 1945 and RFC 2068 specify that the client is not allowed
  to change the method on the redirected request.  However, most
  existing user agent implementations treat 302 as if it

były odpowiedzią 303, wykonując GET na wartości pola Lokalizacja niezależnie od pierwotnej metody żądania. Kody statusu 303 i 307 zostały dodane dla serwerów, które chcą jednoznacznie wyjaśnić, jakiego rodzaju reakcji oczekuje się od klienta.

10.3.4 303 Zobacz inne

Odpowiedź na żądanie można znaleźć pod innym identyfikatorem URI i POWINNA zostać pobrana przy użyciu metody GET na tym zasobie. Ta metoda istnieje głównie po to, aby dane wyjściowe skryptu aktywowanego metodą POST przekierowywały agenta użytkownika do wybranego zasobu. Nowy identyfikator URI nie jest zastępczym odwołaniem do pierwotnie żądanego zasobu. Odpowiedź 303 NIE MOŻE być buforowana, ale odpowiedź na drugie (przekierowane) żądanie może być buforowana.

W polu Lokalizacja w odpowiedzi NALEŻY podać inny identyfikator URI. O ile metoda żądania nie była HEAD, jednostka odpowiedzi POWINNA zawierać krótką notatkę hipertekstową z hiperłączem do nowych identyfikatorów URI.

  Note: Many pre-HTTP/1.1 user agents do not understand the 303
  status. When interoperability with such clients is a concern, the
  302 status code may be used instead, since most user agents react
  to a 302 response as described here for 303.

10.3.5 304 Nie zmodyfikowano

Jeśli klient wykonał warunkowe żądanie GET i dostęp jest dozwolony, ale dokument nie został zmodyfikowany, serwer POWINIEN odpowiedzieć tym kodem stanu. Odpowiedź 304 NIE MOŻE zawierać treści wiadomości i dlatego jest zawsze zakończona pierwszą pustą linią po polach nagłówka.

Odpowiedź MUSI zawierać następujące pola nagłówka:

  - Date, unless its omission is required by section 14.18.1 If a

Bez zegara serwer pochodzenia przestrzega tych reguł, a serwery proxy i klienci dodają własną datę do każdej odpowiedzi otrzymanej bez niej (jak już określono w [RFC 2068], sekcja 14.19), pamięci podręczne będą działać poprawnie.

  - ETag and/or Content-Location, if the header would have been sent
    in a 200 response to the same request
  - Expires, Cache-Control, and/or Vary, if the field-value might
    differ from that sent in any previous response for the same
    variant If the conditional GET used a strong cache validator (see

sekcja 13.3.3), odpowiedź NIE POWINNA zawierać innych nagłówków encji. W przeciwnym razie (tj. Warunkowe GET użyło słabego walidatora), odpowiedź NIE MOŻE zawierać innych nagłówków encji; zapobiega to niespójnościom między treściami jednostek zapisanymi w pamięci podręcznej a zaktualizowanymi nagłówkami.

Jeśli odpowiedź 304 wskazuje, że jednostka nie jest obecnie buforowana, pamięć podręczna MUSI zignorować odpowiedź i powtórzyć żądanie bez warunku.

Jeżeli pamięć podręczna używa odebranej odpowiedzi 304 do aktualizacji wpisu pamięci podręcznej, pamięć podręczna MUSI zaktualizować wpis, aby odzwierciedlić nowe wartości pól podane w odpowiedzi.

10.3.6 305 Użyj proxy

Żądany zasób MUSI być dostępny przez proxy podane w polu Lokalizacja. Pole Location zawiera identyfikator URI proxy. Odbiorca powinien powtórzyć to pojedyncze żądanie za pośrednictwem serwera proxy. 305 odpowiedzi MUSZĄ być generowane tylko przez serwery pochodzenia.

  Note: RFC 2068 was not clear that 305 was intended to redirect a
  single request, and to be generated by origin servers only.  Not
  observing these limitations has significant security consequences.

10.3.7 306 (nieużywany)

Kod stanu 306 był używany w poprzedniej wersji specyfikacji, nie jest już używany, a kod jest zarezerwowany.

10.3.8 307 Tymczasowe przekierowanie

Żądany zasób znajduje się tymczasowo pod innym identyfikatorem URI. Ponieważ przekierowanie MOŻE być czasami zmieniane, klient POWINIEN nadal używać Request-URI dla przyszłych żądań. Ta odpowiedź może zostać zapisana w pamięci podręcznej tylko wtedy, gdy jest to wskazane w polu nagłówka Cache-Control lub Expires.

Tymczasowy URI POWINIEN być podany w polu Location odpowiedzi. O ile metoda żądania nie była HEAD, jednostka odpowiedzi POWINNA zawierać krótką notatkę hipertekstową z hiperłączem do nowych identyfikatorów URI, ponieważ wielu klientów użytkowników sprzed HTTP / 1.1 nie rozumie statusu 307. Dlatego notatka POWINNA zawierać informacje niezbędne użytkownikowi do powtórzenia pierwotnego żądania dotyczącego nowego identyfikatora URI.

Jeśli kod statusu 307 zostanie odebrany w odpowiedzi na żądanie inne niż GET lub HEAD, agent użytkownika NIE MOŻE automatycznie przekierowywać żądania, chyba że zostanie to potwierdzone przez użytkownika, ponieważ może to zmienić warunki, na jakich żądanie zostało wysłane.

Używam 302 do teraz, aż znajdę się poprawną odpowiedź.

Aktualizacja i wnioski:

HTTP 302 jest lepszy, ponieważ wiadomo, że ma najlepszą zgodność z klientami / przeglądarkami.

Vidar Vestnes
źródło
1
Powiedziałbym, że absolutnie metodą książkową byłoby zwrócenie 401 i strony logowania bez przekierowania, ale nie jestem pewien, jakie masz opcje.
Nick Craver
1
@Nie ma sensu, ale obawiałbym się efektów ubocznych, gdybym budował klasyczny system logowania.
Pekka
1
@Pekka - Absolutnie się zgadzam, to zależy od tego, na jakiej platformie jest to wszystko, co można w prosty sposób obsłużyć, także jeśli w grę wchodzi intranet czy internet. Uważam, że ... zazwyczaj uwierzytelnianie odbywa się w inny sposób w intranecie, przynajmniej z mojego doświadczenia.
Nick Craver
@Nick Z 401 „Odpowiedź MUSI zawierać pole nagłówka WWW-Authenticate” - Jak mogę to połączyć z bazą danych MySQL? Czy AuthType Basic i Digest nie są ograniczone do plików konfiguracyjnych Apache, takich jak .htpassword itp.?
Vidar Vestnes
Chcę niestandardowej strony logowania, a nie podstawowego okna dialogowego przeglądarki z pytaniem o nazwę użytkownika i hasło ...
Vidar Vestnes

Odpowiedzi:

70

Powiedziałbym, że 303 zobacz inne 302 Znalezione:

Żądany zasób znajduje się tymczasowo pod innym identyfikatorem URI. Ponieważ przekierowanie może być czasami zmieniane , klient POWINIEN nadal używać identyfikatora URI żądania dla przyszłych żądań. Ta odpowiedź może być zapisywana w pamięci podręcznej tylko wtedy, gdy jest to wskazane w polu nagłówka Cache-Control lub Expires.

Moim zdaniem najbardziej pasuje do strony logowania. Początkowo zastanawiałem się, 303 see otherktóre będzie działać równie dobrze. Po namyśle powiedziałbym, że 302 Foundjest bardziej odpowiedni, ponieważ żądany zasób został znaleziony, wystarczy przejść przez kolejną stronę, zanim będzie można uzyskać do niego dostęp. Odpowiedź nie jest domyślnie zapisywana w pamięci podręcznej, co również jest w porządku.

Pekka
źródło
4
Zgadzam się, ale myślę, że 302 Found wskazuje, że zasób został znaleziony tuż pod innym adresem URL. Dawny. Chcę zobaczyć / moje-wiadomości / odpowiedź serwera z 302, ponieważ „dzisiaj” moje wiadomości znajdują się w „/ login /” (zamiast „/ messages /”) ... Używam 302, ale nie czuję kontekst jest w 100% zgodny. Ponieważ strona logowania jest innym zasobem i nie ma takiej samej treści, jak żądano.
Vidar Vestnes
2
@PHP_Jedi true. 303 może być bardziej odpowiednie z tego punktu widzenia. Jednak 302 jest bardziej niezawodny pod względem zgodności z klientem.
Pekka
1
Tak, myślę, że 303 może lepiej pasować do kontekstu, ponieważ stwierdza, że ​​„Odpowiedź na żądanie można znaleźć pod innym identyfikatorem URI”. To mówi mi, że to nie sam zasób można znaleźć w innym URI, ale tylko odpowiedź na to żądanie.
Vidar Vestnes
3
@PHP_Jedi Nie jestem pewien, czy warto poświęcić temu tyle czasu. Zarówno klienci, jak i serwery w świecie http muszą i tak być niezwykle liberalne i odporne na błędy, więc nie będzie żadnej różnicy, czy używasz, 302czy 303, poza tym, że 302jest to lepiej znane. Poziom szczegółowości jest dla mnie godny pochwały i zawsze dobrze jest zrobić wszystko dobrze, ale zbyt duży wysiłek może być daremny w tej konkretnej dziedzinie.
Pekka
30
Do Twojej wiadomości: Google wydaje 302s
David Murdoch,
52

Jest to nadużycie mechanizmu przekierowania HTTP. Jeśli użytkownik nie jest autoryzowany, Twoja aplikacja musi wrócić 401 Unauthorized. W przypadku, gdy użytkownik jest autoryzowany, ale nie ma dostępu do żądanego zasobu, 403 Forbiddennależy go zwrócić.

Powinieneś zrobić to przekierowanie po stronie klienta, np. Przez javascript. kod statusu przekierowania, ponieważ nie istnieje wymagana autoryzacja . Używanie 30x do tego nie jest zgodne z HTTP.

Jak myśleć o kodach stanu HTTP autorstwa Marka Nottinghama

401 Unauthorized uruchamia mechanizm uwierzytelniania żądań HTTP.

401 Unauthorizedkod statusu wymaga obecności WWW-Authenticatenagłówka obsługującego różne typy uwierzytelniania:

WWW-Authenticate: <type> realm = <realm>

Bearer, OAuth, Basic, Digest, Cookie itp

filip26
źródło
21
401 może nie być odpowiedni w niektórych przypadkach jako A server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header field( RFC ), a nie wszystkie systemy logowania używają tego nagłówka.
starbeamrainbowlabs
6
Załóżmy, że odświeżasz chronioną stronę; JavaScript po stronie klienta nie będzie wymagał żadnych zmian, a przeglądarka wyświetli okno logowania zamiast przekierowywania użytkownika na stronę logowania - więc jedynym sposobem jest użycie kodu 30x.
Claude Brisson
2
Golang nie może użyć 401 do przekierowania. Oznacza to, że do przekierowań powinniśmy używać 30 *.
EIMEI
4
@EIMEI Idąc za twoim rozumowaniem, gdyby inny język lub biblioteka zmusiły cię do korzystania z 401, Internet byłby skazany na zagładę. Mój punkt jest: co mówisz, wskazuje na problem z Golang (chociaż uważam, że to dziwne, że byłoby mieć taką konstrukcję, aby uniemożliwić wysyłanie 401s!)
Greg
2
@starbeamrainbowlabs Istnieje wersja robocza uwierzytelniania HTTP opartego na plikach cookie jako opcja w nagłówku WWW-Authenticate. Zobacz: tools.ietf.org/html/draft-broyer-http-cookie-auth-00
aef
12

Myślę, że odpowiednim rozwiązaniem jest nagłówek HTTP 401 (Not Authorized).

http://en.wikipedia.org/wiki/HTTP_codes#4xx_Client_Error

Celem tego nagłówka jest właśnie to. Ale zamiast przekierowywać na stronę logowania, prawidłowy proces wyglądałby tak:

  • Niezalogowany użytkownik próbuje uzyskać dostęp do strony z ograniczeniami logowania.
  • system wskazuje, że użytkownik nie jest zalogowany
  • system zwraca nagłówek HTTP 401 ORAZ wyświetla formularz logowania w tej samej odpowiedzi (nie przekierowaniu).

Jest to dobra praktyka, np. Zapewnienie użytecznej strony 404 z linkami do mapy witryny i formularzem wyszukiwania.

Do zobaczenia.

Davis Peixoto
źródło
20
Dokument RFC stwierdza: „Odpowiedź MUSI zawierać pole nagłówka WWW-Authenticate (sekcja 14.46) zawierające wyzwanie mające zastosowanie do żądanego zasobu”. Odpowiedź 401 ma zastosowanie tylko w przypadku korzystania ze schematu uwierzytelniania HTTP.
bshacklett
4
W takim przypadku 403 byłoby lepsze, ponieważ stwierdza, że ​​dostęp jest po prostu zabroniony, a nagłówek autoryzacji nie pomoże
olanod
@bshacklett WWW-Authenticate może być używany razem z wieloma schematami uwierzytelniania (np. Bearer, OAuth). Zobacz developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… i iana.org/ assignments
http
Istnieje wersja robocza uwierzytelniania HTTP opartego na plikach cookie jako opcja w nagłówku WWW-Authenticate. Zobacz: tools.ietf.org/html/draft-broyer-http-cookie-auth-00
aef