В чем разница между перенаправлением 302 и 307?


208

В чем разница между ответом a 302 FOUNDи 307 TEMPORARY REDIRECTHTTP?

Спецификация W3, кажется, указывает, что они оба используются для временных перенаправлений, и ни один из них не может быть кэширован, если ответ специально не разрешает это.

Ответы:


99

Разностные касается переадресации POST, PUTи DELETEзапросов , и какие ожидания сервера являются для поведения агента пользователя ( RFC 2616):

Примечание: RFC 1945 и RFC 2068 указывают, что клиенту не разрешено изменять метод в перенаправленном запросе. Однако большинство существующих реализаций пользовательского агента обрабатывают 302 так, как если бы это был ответ 303, выполняя GET для значения поля Location независимо от исходного метода запроса. Коды состояния 303 и 307 были добавлены для серверов, которые хотят однозначно прояснить, какой тип реакции ожидается от клиента.

Также читайте статью в Википедии о кодах перенаправления 30x .


Итак, с точки зрения парсера / агента / браузера, мы можем просто считать 302 и 307 одинаковыми, верно? ( Точно такой же кусок кода можно использовать для обработки обоих случаев без дальнейшего различия?)
Pacerier

Нет - вы можете рассматривать 302 и 303 как идентичные, но 307 отличается.
Квентин Скоусен

@kkhugs, Ни в коем случае браузер 1.0 не должен делать get-302 так же, как get-307 в браузерах 1.1. Браузер версии 1.0 должен выполнять post-302 так же, как и get-302, за исключением того, что для начала необходимо подтверждение пользователя, а метод должен быть post.
Pacerier

Браузер версии 1.1 должен выполнять get-302 так же, как и get-307.
Pacerier

161

307 появился потому, что пользовательские агенты приняли де-факто поведение, чтобы принимать запросы POST, которые получают ответ 302 и отправляют запрос GET в заголовок ответа Location.

Это неправильное поведение - только 303 должен заставить POST превратиться в GET. Пользовательские агенты должны (но не) придерживаться метода POST при запросе нового URL, если исходный запрос POST возвратил 302.

307 был введен для того, чтобы серверы давали понять агенту пользователя, что изменение метода не должно выполняться клиентом при следовании заголовку ответа Location.


3
Какие-либо примеры пользовательских агентов, которые отвечают неправильно? Это обычно очень маленький процент посетителей?
goodguys_activate

6
@ makerofthings7 Все браузеры обрабатывают 302неправильно. Chrome 30, IE10. Это стало де-факто неправильной реализацией; это не может быть изменено, потому что многие сайты ошибочно выдают ошибку 302. На самом деле ASP.net MVC неправильно выдает ошибку 302, в зависимости от того, что браузеры обрабатывают ее неправильно.
Ян Бойд

1
@IanBoyd Единственная причина, по которой фреймворки делают это, заключается в том, что 303она также была введена 307в спецификации HTTP 1.1 и поэтому обеспечивает обратную совместимость с пользовательскими агентами HTTP 1.0. Конечно, реальный вопрос в том, должны ли мы по-прежнему обрабатывать пользовательские агенты HTTP 1.0 вообще?
ewanm89

1
@ ewanm89 Похоже, что фреймворк может создать правильно названный метод ответа (например Response.RedirectSeeOther), а если клиент не 1.1 (например GET /foo.html, GET /foo.html HTTP/1.0), то выпустить наследие 302.
Ян Бойд

Похоже, 302 = 303 при перенаправлении.
ви

60

Хорошим примером 307 Internal Redirectдействия является случай, когда Google Chrome обнаруживает HTTP-вызов домена, который, как он знает, требует строгой транспортной безопасности.

Браузер перенаправляет без проблем, используя тот же метод, что и исходный вызов.

HTST 307 Внутреннее перенаправление


2
Знаете ли вы, когда Google реализовал эту функцию?
Tijme

2
Да, именно здесь я наблюдаю, как это происходит - наш сервер не отправляет это - в chrome devtools это выглядит так, как будто, но это просто chrome, выполняющий перенаправление, потому что у нас есть заголовок Strict Transport Security
Майк

16

блок-схема

  • 301: постоянное перенаправление: URL старый и должен быть заменен. Браузеры кешируют это.
    Пример использования: URL перемещен из /register-form.htmlв signup-form.html.
    Метод изменится на GET в соответствии с RFC 7231: «По историческим причинам пользовательский агент МОЖЕТ изменить метод запроса с POST на GET для последующего запроса».
  • 302: временное перенаправление. Используйте только для клиентов HTTP / 1.0. Этот код состояния не должен изменять метод, но браузеры все равно сделали это. В RFC говорится: «Многие пользовательские агенты до HTTP / 1.1 не понимают [303]. Когда возникает проблема взаимодействия с такими клиентами, вместо этого можно использовать код состояния 302, так как большинство пользовательских агентов реагируют на ответ 302, как описано здесь. за 303. " Конечно, некоторые клиенты могут реализовать его в соответствии со спецификацией, поэтому, если совместимость с такими древними клиентами не является реальной проблемой, 303 лучше для получения стабильных результатов.
  • 303: временное перенаправление, изменение метода на GET.
    Пример использования: если браузер отправил POST /register.php, затем загрузите (GET) /success.html.
  • 307: временное перенаправление, идентичное повторение запроса.
    Пример использования: если браузер отправил POST в /register.php, то это говорит ему повторить POST в /signup.php.
  • 308: постоянное перенаправление, идентичное повторение запроса. Где 307 является эквивалентом «без изменения метода» 303, этот статус 308 является аналогом «отсутствия изменения метода» 301.

RFC 7231 (с 2014 года) очень читабелен и не слишком многословен. Если вы хотите знать точный ответ, рекомендуем прочитать. Некоторые другие ответы используют RFC 2616 от 1999 года, но ничего не изменилось.

RFC 7238 определяет статус 308. Он считается экспериментальным, но он уже был поддержан всеми основными браузерами в 2016 году.


302 не считается устаревшим.
Джулиан Решке

@JulianReschke Википедия говорит, что «302 был заменен 303 и 307.» Может быть, это потому, что я не являюсь носителем языка, но для меня (в этом контексте) «заменено» и «устарело» означает одно и то же: использовать 303 или 307, но не 302. Я читаю это неправильно?
Люк

Что не так, так это предположение, что Википедия имеет право голоса по этому поводу. Если 302 устарел, HTTP сказал бы так.
Джулиан Решке

@JulianReschke Достаточно справедливо, я взял к источнику и waddayaknow? Ты совершенно прав. RFC на самом деле очень понятен, и даже при определенных условиях они даже рекомендуют 302. Ни один из «обновленных» и «устаревших» RFC, упомянутых сверху, не касается кодов состояния, поэтому я думаю, что этот документ 1999 года действительно является последним, что у нас есть. Я обновлю свой ответ.
Люк

Что актуально, так это реестр кодов статуса IANA и, таким образом, в данном случае RFC 7231.
Джулиан Решке,

8

ОЖИДАЕТСЯ для 302: перенаправление использует тот же метод запроса POST для NEW_URL

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

ACTUAL для 302, 303: метод запроса перенаправления изменений с POST на GET для 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)

ACTUAL для 307: редирект использует тот же метод запроса POST для NEW_URL

CLIENT POST OLD_URL -> SERVER 307 NEW_URL -> CLIENT POST NEW_URL

2

302 - это временное перенаправление, которое генерируется сервером, тогда как 307 - это внутренний ответ на перенаправление, генерируемый браузером. Внутреннее перенаправление означает, что перенаправление выполняется автоматически внутренним браузером, в основном браузер самостоятельно изменяет введенный URL-адрес с http на https в запросе get перед тем, как сделать запрос, поэтому запрос на незащищенное соединение никогда не выполняется в Интернете. Будет ли браузер изменять URL-адрес на https или нет, зависит от списка предварительной загрузки hsts, который поставляется с предустановленным браузером. Вы также можете добавить любой сайт, поддерживающий https, в список, введя домен в список предварительной загрузки hsts вашего браузера, который находится на chrome: //net-internals/#hsts. Еще одна вещь, которую доменные сайты могут добавлять владельцы предварительно загрузить список, заполнив форму на https://hstspreload.org/так что он предустанавливается в браузерах для каждого пользователя, хотя я упоминаю, что вы можете сделать это специально для себя.


Позвольте мне объяснить на примере:
я сделал запрос на получение http://www.pentesteracademy.com, который поддерживает только https, и у меня нет этого домена в моем списке предварительной загрузки hsts в моем браузере, так как владелец сайта не зарегистрировался для него прийти с предустановленным списком предзагрузки hsts. Запрос GET на незащищенную версию сайта перенаправляется на безопасную версию (см. Заголовок http с указанием местоположения для этого в ответе на изображении выше). Теперь я добавляю сайт в свой собственный список предварительной загрузки браузера, добавляя его домен в форме Добавить домен hsts в chrome: // net-internals / # hsts, которая изменяет мой личный список предварительной загрузки в моем браузере Chrome. Обязательно выбирайте для включения субдомены для Вариант СТС есть. Давайте теперь посмотрим запрос и ответ для того же веб-сайта после добавления его в список предварительной загрузки hsts.заголовки запроса и ответа



заголовки запроса и ответа
вы можете увидеть внутреннее перенаправление 307 там в заголовках ответов, фактически этот ответ генерируется вашим браузером, а не сервером.
Кроме того, список предварительной загрузки HSTS может помочь предотвратить доступ пользователей к небезопасной версии сайта, поскольку перенаправление 302 подвержено быстрым атакам.
Надеюсь, я немного помог вам понять больше о перенаправлениях.


2

Изначально был просто 302

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

Идея в том, что:

  • если вы делаете GETв каком-то месте, вы бы перенаправили GETна новый URL
  • если вы делаете POSTв каком-то месте, вы бы перенаправили POSTна новый URL
  • если вы делаете PUTв каком-то месте, вы бы перенаправили PUTна новый URL
  • если вы делаете DELETEв каком-то месте, вы бы перенаправили DELETEна новый URL
  • и т.д

К сожалению, каждый браузер сделал это неправильно. Получая a 302, они всегда переключаются GETна новый URL, а не повторяют запрос с одним и тем же глаголом ( например , POST):

  • Мозаика сделала это неправильно
  • Netscape скопировал ошибки в Mosaic; поэтому они ошиблись
  • Internet Explorer скопировал ошибки в Netscape; поэтому они ошиблись

Это стало де-факто неправильно.

Все браузеры 302ошиблись. Так 303и 307были созданы.

| Ответ | Что должны делать браузеры | Что на самом деле делают браузеры | | ------------------------ | ------------------------ --- | --------------------------- | | 302 найдено | Повторить запрос с новым URL | ПОЛУЧИТЬ с новым URL | | 303 См. Другое | ПОЛУЧИТЬ с новым URL | ПОЛУЧИТЬ с новым URL | | 307 Временный редирект | Повторить запрос с новым URL | Повторить запрос с новым URL |

В форме диаграммы

5 различных видов перенаправлений:

╔═══════════╤════════════════════════════════════════════════╗
║           │                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)    ║
╚═══════════╧════════════════════════╧═══════════════════════╝

В качестве альтернативы:

| 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         |

1

Кроме того, для администраторов сервера может быть важно отметить, что браузеры могут отображать подсказку для пользователя, если вы используете перенаправление 307.

Например *, Firefox и Opera будут запрашивать у пользователя разрешение на перенаправление, тогда как Chrome, IE и Safari будут выполнять перенаправление прозрачно.

* за пуленепробиваемые SSL и TLS (стр. 192).


Это верно только для небезопасных запросов, таких как POST.
Джулиан Решке

0

В некоторых случаях злоумышленник может злоупотреблять перенаправлениями 307, чтобы узнать учетные данные жертвы.

Дополнительную информацию можно найти в разделе 3.1 из универсальной формальной анализа безопасности OAuth 2.0 .

Авторы вышеупомянутой статьи предлагают следующее:

Фикс. В отличие от текущей формулировки в стандарте OAuth, точный метод перенаправления не является деталью реализации, но необходим для безопасности OAuth. В стандарте HTTP ( RFC 7231 ) однозначно определено только перенаправление 303, чтобы отбрасывать тело запроса HTTP POST. Все остальные коды состояния перенаправления HTTP, включая наиболее часто используемый код 302, оставляют браузеру возможность сохранять запрос POST и данные формы. На практике браузеры обычно переписывают запрос GET, тем самым отбрасывая данные формы, за исключением 307 перенаправлений. Поэтому стандарт OAuth должен требовать 303 перенаправления для шагов, упомянутых выше, чтобы решить эту проблему.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.