Jaka jest różnica między przekierowaniem 302 a 307?

208

Jaka jest różnica między odpowiedzią 302 FOUNDa a 307 TEMPORARY REDIRECTodpowiedzią HTTP?

Specyfikacja W3 wydaje się wskazywać, że oba są używane do tymczasowych przekierowań i nie można ich buforować, chyba że reakcja na to wyraźnie zezwala.

Zach Hirsch
źródło

Odpowiedzi:

99

Różnica dotyczy przekierowujące POST, PUToraz DELETEwnioski i jakie oczekiwania serwera są za zachowanie agenta użytkownika ( RFC 2616):

Uwaga: RFC 1945 i RFC 2068 określają, że klient nie może zmieniać metody przekierowanego żądania. Jednak większość istniejących implementacji agenta użytkownika traktuje 302 tak, jakby była odpowiedzią 303, wykonując GET na wartości pola Lokalizacja niezależnie od oryginalnej metody żądania. Kody stanu 303 i 307 zostały dodane dla serwerów, które chcą jednoznacznie wyjaśnić, jakiego rodzaju reakcji oczekuje się od klienta.

Przeczytaj także artykuł w Wikipedii na temat 30- krotnych kodów przekierowań .

Franci Penov
źródło
Więc z perspektywy parsera / agenta / przeglądarki możemy po prostu traktować 302 i 307 jako identyczne, prawda? ( Dokładnie ten sam fragment kodu może być wykorzystany do obsługi obu przypadków bez dalszego rozróżnienia?)
Pacerier
Nie - możesz traktować 302 i 303 jako identyczne, ale 307 jest inne.
Quentin Skousen
@kkhugs, Nie ma mowy, że przeglądarka 1.0 jest wymagana do wykonania get-302 w taki sam sposób, jak get-307 odbywa się w przeglądarkach 1.1. Przeglądarka 1.0 jest wymagana do działania po 302 w taki sam sposób, jak robi get-302, z tym że musi najpierw wymagać potwierdzenia użytkownika, a metoda musi być dostępna.
Pacerier
Do wykonania get-302 wymagana jest przeglądarka 1.1 w taki sam sposób, jak robi get-307.
Pacerier
161

307 powstało, ponieważ agenty użytkownika przyjęły jako de facto zachowanie przyjmujące żądania POST, które otrzymują odpowiedź 302 i wysyłają żądanie GET do nagłówka odpowiedzi lokalizacji.

To jest nieprawidłowe zachowanie - tylko 303 powinno spowodować, że test POST zmieni się w GET. Agenty użytkownika powinny (ale nie muszą) trzymać się metody POST, gdy żądają nowego adresu URL, jeśli pierwotne żądanie POST zwróciło wartość 302.

Wprowadzono 307, aby umożliwić serwerom wyjaśnienie agentowi użytkownika, że klient nie powinien dokonywać zmian metody podczas podążania za nagłówkiem odpowiedzi Lokalizacja.

Christopher Orr
źródło
3
Jakieś przykłady programów użytkownika, które reagują niepoprawnie? Czy zazwyczaj jest to bardzo mały procent odwiedzających?
goodguys_activate
6
@ makerofthings7 Wszystkie przeglądarki mają 302nieprawidłową obsługę . Chrome 30, IE10. Stało się de facto nieprawidłową implementacją; nie można tego zmienić, ponieważ tak wiele witryn wydaje błąd omyłkowo 302. W rzeczywistości ASP.net MVC niepoprawnie wydaje 302, w zależności od tego, że przeglądarki nieprawidłowo go obsługują.
Ian Boyd
1
@IanBoyd Jedyne powody, dla których to robią, to dlatego, że 303wprowadzono je również 307w specyfikacji HTTP 1.1, a zatem umożliwia zgodność wsteczną z agentami użytkownika HTTP 1.0. Oczywiście, prawdziwe pytanie brzmi: czy nadal powinniśmy w ogóle obsługiwać programy klienckie HTTP 1.0?
ewanm89
1
@ ewanm89 Wygląda na to, że środowisko może stworzyć poprawnie nazwaną metodę odpowiedzi (np. Response.RedirectSeeOther), a jeśli klient nie jest w wersji 1.1 (np. ) GET /foo.html, wydaj starszą wersję . GET /foo.html HTTP/1.0302
Ian Boyd
Po przekierowaniu wygląda to na 302 = 303.
vee
60

Dobrym przykładem tego 307 Internal Redirectdziałania jest sytuacja, gdy Google Chrome napotyka połączenie HTTP do domeny, o której wie, że wymaga ścisłego bezpieczeństwa transportu.

Przeglądarka płynnie przekierowuje, korzystając z tej samej metody, co oryginalne wywołanie.

Wewnętrzne przekierowanie HTST 307

Kristian Williams
źródło
2
Czy wiesz, kiedy Google wdrożyło tę funkcję?
Tijme,
2
Tak, właśnie to widzę - nasz serwer tego nie wysyła - w chrome devtools wygląda to tak, ale po prostu chrome wykonuje przekierowanie, ponieważ mamy nagłówek Strict Transport Security
Mike Nelson
16

Schemat blokowy

  • 301: trwałe przekierowanie: adres URL jest stary i powinien zostać zastąpiony. Przeglądarki to buforują.
    Przykładowe użycie: URL przeniesiono z /register-form.htmldo signup-form.html.
    Metoda zmieni się na GET, zgodnie z RFC 7231: „Z przyczyn historycznych klient użytkownika MOŻE zmienić metodę żądania z POST na GET dla następnego żądania”.
  • 302: tymczasowe przekierowanie. Używaj tylko dla klientów HTTP / 1.0. Ten kod stanu nie powinien zmieniać metody, ale i tak zrobiły to przeglądarki. RFC mówi: „Wiele aplikacji klienckich wcześniejszych niż HTTP / 1.1 nie rozumie [303]. Gdy problem stanowi interoperacyjność z takimi klientami, zamiast tego można zastosować kod stanu 302, ponieważ większość programów użytkownika reaguje na odpowiedź 302, jak opisano tutaj dla 303. ” Oczywiście niektórzy klienci mogą wdrożyć go zgodnie ze specyfikacją, więc jeśli interoperacyjność z tak starożytnymi klientami nie stanowi prawdziwego problemu, 303 jest lepsze dla uzyskania spójnych wyników.
  • 303: tymczasowe przekierowanie, zmiana metody na GET.
    Przykładowe użycie: jeśli przeglądarka wysłała POST do /register.php, to teraz załaduj (GET) /success.html.
  • 307: tymczasowe przekierowanie, identyczne powtarzanie żądania.
    Przykładowe użycie: jeśli przeglądarka wysłała test POST /register.php, oznacza to, że należy ponownie wykonać test POST o /signup.php.
  • 308: trwałe przekierowanie, identyczne powtarzanie żądania. Tam, gdzie 307 jest odpowiednikiem „bez zmiany metody” 303, ten stan 308 jest odpowiednikiem „bez zmiany metody” 301.

RFC 7231 (od 2014 roku) jest bardzo czytelny i nie przesadza. Jeśli chcesz poznać dokładną odpowiedź, jest to zalecana lektura. Niektóre inne odpowiedzi używają RFC 2616 z 1999 roku, ale nic się nie zmieniło.

RFC 7238 określa status 308. Jest uważany za eksperymentalny, ale był już obsługiwany przez wszystkie główne przeglądarki w 2016 roku.

Luc
źródło
302 nie jest przestarzałe.
Julian Reschke
@JulianReschke Wikipedia mówi „302 został zastąpiony przez 303 i 307”. Może dlatego, że nie jestem native speakerem, ale dla mnie (w tym kontekście) zastąpienie i przestarzałe oznacza to samo: albo użyj 303 albo 307, ale nie 302. Czy to źle rozumiem?
Luc
Nieprawidłowe jest założenie, że Wikipedia ma coś do powiedzenia na ten temat. Gdyby 302 było przestarzałe, HTTP by to powiedział.
Julian Reschke
@JulianReschke Do przyjęcia, wziąłem do źródła i waddayaknow? Masz całkowitą rację. RFC jest w rzeczywistości bardzo zrozumiały, a nawet polecają 302 pod pewnymi warunkami. Żaden z „zaktualizowanych przez” i „przestarzałych” przez RFC wymienionych powyżej nie dotyczy kodów statusu, więc sądzę, że ten dokument z 1999 roku jest rzeczywiście najnowszy. Zaktualizuję moją odpowiedź.
Luc
Istotny jest rejestr kodu stanu IANA, a zatem w tym przypadku RFC 7231.
Julian Reschke
8

OCZEKIWANY dla 302: przekierowanie używa tej samej metody żądania POST na NEW_URL

CLIENT POST OLD_URL -> SERVER 302 NEW_URL -> CLIENT POST NEW_URL

RZECZYWISTY dla 302, 303: przekieruj metodę żądania zmiany z POST na GET na NEW_URL

CLIENT POST OLD_URL -> SERVER 302 NEW_URL -> CLIENT GET NEW_URL (redirect uses GET)
CLIENT POST OLD_URL -> SERVER 303 NEW_URL -> CLIENT GET NEW_URL (redirect uses GET)

RZECZYWISTY dla 307: przekierowanie używa tej samej metody żądania POST na NEW_URL

CLIENT POST OLD_URL -> SERVER 307 NEW_URL -> CLIENT POST NEW_URL
Roy Hyunjin Han
źródło
2

302 to tymczasowe przekierowanie, które jest generowane przez serwer, podczas gdy 307 jest wewnętrzną odpowiedzią na przekierowanie generowaną przez przeglądarkę. Wewnętrzne przekierowanie oznacza, że ​​przekierowanie odbywa się automatycznie wewnętrznie przez przeglądarkę, w zasadzie przeglądarka sama zmienia wprowadzony adres URL z http na https w zapytaniu get przed wysłaniem żądania, więc żądanie niezabezpieczonego połączenia nigdy nie jest wysyłane do Internetu. To, czy przeglądarka zmieni adres URL na https, zależy od listy wstępnie załadowanych plików hsts, które są fabrycznie zainstalowane z przeglądarką. Możesz także dodać do listy dowolną witrynę, która obsługuje https, wpisując domenę na listę wstępnego ładowania hsts własnej przeglądarki, która znajduje się na chrome: //net-internals/#hsts.Inne strony domen mogą być dodawane przez ich właścicieli wstępnie załadować listę, wypełniając formularz na https://hstspreload.org/dzięki czemu jest instalowany w przeglądarkach dla każdego użytkownika, nawet jeśli wspomniałem, że możecie zrobić to także dla siebie.


Pozwól mi wyjaśnić na przykładzie: wysłałem
prośbę o pobranie do http://www.pentesteracademy.com, która obsługuje tylko https i nie mam tej domeny na mojej liście wstępnego ładowania hsts w przeglądarce, ponieważ właściciel witryny nie zarejestrował się dla niej w zestawie z wstępnie zainstalowaną listą wstępnego ładowania hsts. Żądanie GET dotyczące niezabezpieczonej wersji witryny jest przekierowywane do bezpiecznej wersji (patrz nagłówek http o nazwie lokalizacja w odpowiedzi na powyższym obrazie). Teraz dodaję witrynę do mojej listy wstępnego ładowania przeglądarki, dodając jej domenę w formie Dodaj domenę hsts na chrome: // net-internals / # hsts, która modyfikuje moją osobistą listę wstępnego ładowania w mojej przeglądarce Chrome. Pamiętaj, aby wybrać zawierać poddomeny dla Opcja STS tam. Zobaczmy teraz żądanie i odpowiedź dla tej samej witryny po dodaniu jej do listy wstępnego ładowania hsts.nagłówki żądań i odpowiedzi



nagłówki żądań i odpowiedzi
w nagłówkach odpowiedzi widać wewnętrzne przekierowanie 307, w rzeczywistości ta odpowiedź jest generowana przez przeglądarkę, a nie przez serwer.
Również lista wstępnego ładowania HSTS może pomóc użytkownikom w dotarciu do niezabezpieczonej wersji strony, ponieważ przekierowania 302 są podatne na ataki mitm.
Mam nadzieję, że nieco pomogłem ci zrozumieć więcej na temat przekierowań.

Simranjeet Singh
źródło
2

Pierwotnie było tylko 302

| Response               | What browsers should do   |
|------------------------|---------------------------|
| 302 Found              | Redo request with new url |

Chodzi o to, że:

  • jeśli robisz GETw jakiejś lokalizacji, powtórzyłbyś swój GETpod nowym adresem URL
  • jeśli robisz POSTw jakiejś lokalizacji, powtórzyłbyś swój POSTpod nowym adresem URL
  • jeśli robisz PUTw jakiejś lokalizacji, powtórzyłbyś swój PUTpod nowym adresem URL
  • jeśli robisz DELETEw jakiejś lokalizacji, powtórzyłbyś swój DELETEpod nowym adresem URL
  • itp

Niestety każda przeglądarka zrobiła to źle. Kiedy dostaję 302, to oni zawsze przełączyć się GETna nowy adres URL, zamiast Ponowna próba wniosek z tego samego czasownika ( np , POST):

  • Mozaika zrobiła to źle
  • Netscape skopiował błędy w Mosaic; więc źle zrozumieli
  • Internet Explorer skopiował błędy w Netscape; więc źle zrozumieli

Stało się de facto źle.

Wszystkie przeglądarki się 302pomyliły. Więc 303i 307zostały stworzone.

| Odpowiedź | Co powinny zrobić przeglądarki | Co faktycznie robią przeglądarki | | ------------------------ | ------------------------ --- | --------------------------- | | 302 Znaleziono | Ponów żądanie z nowym adresem URL POBIERZ z nowym adresem URL | 303 Zobacz inne | POBIERZ z nowym adresem URL POBIERZ z nowym adresem URL | 307 Tymczasowe przekierowanie | Ponów żądanie z nowym adresem URL Ponów żądanie z nowym adresem URL

W formie wykresu

5 różnych rodzajów przekierowań:

╔═══════════╤════════════════════════════════════════════════╗
║           │                Switch to GET?                  ║
║ Temporary │          No            │         Yes           ║
╠═══════════╪════════════════════════╪═══════════════════════╣
║ No        │ 308 Permanent Redirect │ 301 Moved Permanently ║
╟───────────┼────────────────────────┼───────────────────────╢
║ Yes       │ 307 Temporary Redirect │ 303 See Other         ║
║           │ 302 Found (intended)   │ 302 Found (actual)    ║
╚═══════════╧════════════════════════╧═══════════════════════╝

Alternatywnie:

| Response                 | Switch to get? | Temporary? |
|--------------------------|----------------|------------|
| 301 Moved Permanently    | No             | No         |
| 302 Found (intended)     | No             | Yes        |
| 302 Found (actual)       | Yes            | Yes        |
| 303 See Other            | Yes            | Yes        |
| 307 Temporary Redirect   | No             | Yes        |
| 308 Permanent Redirect   | No             | No         |
Ian Boyd
źródło
1

Również dla administratorów serwerów może być ważne, aby pamiętać, że przeglądarki mogą wyświetlać użytkownikowi monit, jeśli użyjesz przekierowania 307.

Na przykład *, Firefox i Opera poprosiłyby użytkownika o zgodę na przekierowanie, podczas gdy Chrome, IE i Safari wykonałyby przekierowanie w sposób transparentny.

* na Bulletproof SSL i TLS (strona 192).

Pacerier
źródło
Dotyczy to tylko niebezpiecznych żądań, takich jak POST.
Julian Reschke,
0

W niektórych przypadkach napastnik może wykorzystać 307 przekierowań, aby poznać dane uwierzytelniające ofiary.

Więcej informacji można znaleźć w rozdziale 3.1 od A Comprehensive analiza formalna Bezpieczeństwa OAuth 2.0 .

Autorzy powyższej pracy sugerują, co następuje:

Naprawić. W przeciwieństwie do obecnego brzmienia standardu OAuth, dokładna metoda przekierowania nie jest szczegółem implementacji, ale jest niezbędna dla bezpieczeństwa OAuth. W standardzie HTTP ( RFC 7231 ) tylko przekierowanie 303 jest zdefiniowane jednoznacznie, aby usunąć treść żądania HTTP POST. Wszystkie inne kody statusu przekierowania HTTP, w tym najczęściej używane 302, pozostawiają przeglądarce opcję zachowania żądania POST i danych formularza. W praktyce przeglądarki zazwyczaj przepisują na żądanie GET, usuwając w ten sposób dane formularza, z wyjątkiem 307 przekierowań. Dlatego standard OAuth powinien wymagać przekierowań 303 dla wyżej wymienionych kroków, aby rozwiązać ten problem.

MS Dousti
źródło