Какой правильный код состояния HTTP при перенаправлении на страницу входа?

133

Когда пользователь не вошел в систему и пытается получить доступ к странице, требующей входа в систему, каков правильный код состояния HTTP для перенаправления на страницу входа?

Я спрашиваю, потому что ни один из кодов ответов 3xx, установленных W3C, похоже, не соответствует требованиям:

10.3.1 300 множественных выборов

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

Если это не запрос HEAD, ответ ДОЛЖЕН включать объект, содержащий список характеристик ресурса и местоположения, из которых пользователь или пользовательский агент может выбрать наиболее подходящий. Формат объекта определяется типом носителя, указанным в поле заголовка Content-Type. В зависимости от формата и возможностей

агент пользователя, выбор наиболее подходящего варианта МОЖЕТ быть выполнен автоматически. Однако эта спецификация не определяет никаких стандартов для такого автоматического выбора.

Если у сервера есть предпочтительный выбор представления, он ДОЛЖЕН включить конкретный URI для этого представления в поле Location; пользовательские агенты МОГУТ использовать значение поля Location для автоматического перенаправления. Этот ответ кэшируется, если не указано иное.

10.3.2 301 перемещено навсегда

Запрошенному ресурсу был назначен новый постоянный URI, и любые будущие ссылки на этот ресурс ДОЛЖНЫ использовать один из возвращенных URI. Клиенты с возможностями редактирования ссылок должны автоматически связывать ссылки на Request-URI с одной или несколькими новыми ссылками, возвращаемыми сервером, где это возможно. Этот ответ кэшируется, если не указано иное.

Новый постоянный URI ДОЛЖЕН быть задан в поле Location в ответе. Если метод запроса не был HEAD, объект ответа ДОЛЖЕН содержать короткую гипертекстовую заметку с гиперссылкой на новый URI.

Если код состояния 301 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, при которых был выполнен запрос.

  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 найдено

Запрошенный ресурс временно находится под другим URI. Поскольку перенаправление может иногда изменяться, клиенту СЛЕДУЕТ продолжать использовать Request-URI для будущих запросов. Этот ответ может быть кэширован, только если он указан в поле заголовка Cache-Control или Expires.

Временный URI ДОЛЖЕН быть задан в поле Location в ответе. Если метод запроса не был HEAD, объект ответа ДОЛЖЕН содержать короткую гипертекстовую заметку с гиперссылкой на новый URI.

Если код состояния 302 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, при которых запрос был выпущен.

  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

были ответом 303, выполняющим GET для значения поля Location независимо от исходного метода запроса. Коды состояния 303 и 307 были добавлены для серверов, которые хотят однозначно прояснить, какой тип реакции ожидается от клиента.

10.3.4 303 См. Другое

Ответ на запрос можно найти под другим URI, и его СЛЕДУЕТ получить с помощью метода GET для этого ресурса. Этот метод существует прежде всего для того, чтобы разрешить вывод активированного POST сценария перенаправить пользовательский агент на выбранный ресурс. Новый URI не является заменой ссылки на первоначально запрошенный ресурс. Ответ 303 НЕ ДОЛЖЕН кэшироваться, но ответ на второй (перенаправленный) запрос может быть кэширован.

Другой URI ДОЛЖЕН быть указан в поле Location в ответе. Если метод запроса не был HEAD, объект ответа ДОЛЖЕН содержать короткую гипертекстовую заметку с гиперссылкой на новый 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 Не модифицировано

Если клиент выполнил условный запрос GET и доступ разрешен, но документ не был изменен, сервер ДОЛЖЕН ответить этим кодом состояния. Ответ 304 НЕ ДОЛЖЕН содержать тело сообщения и поэтому всегда заканчивается первой пустой строкой после полей заголовка.

Ответ ДОЛЖЕН включать следующие поля заголовка:

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

Clockless origin server подчиняется этим правилам, а прокси и клиенты добавляют свою собственную дату к любому ответу, полученному без нее (как уже указано в [RFC 2068], раздел 14.19), кеши будут работать правильно.

  - 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

раздел 13.3.3), ответ НЕ ДОЛЖЕН включать другие заголовки объектов. В противном случае (т. Е. Условный GET использовал слабый валидатор), ответ НЕ ДОЛЖЕН включать другие заголовки объекта; это предотвращает несоответствия между кэшированными сущностями и обновленными заголовками.

Если ответ 304 указывает объект, который в данный момент не кэширован, то кэш ДОЛЖЕН игнорировать ответ и повторить запрос без условия.

Если кэш использует полученный ответ 304 для обновления записи в кэше, кэш ДОЛЖЕН обновить запись, чтобы отразить любые новые значения полей, указанные в ответе.

10.3.6 305 Использовать прокси

К запрошенному ресурсу ДОЛЖНЫ обращаться через прокси-сервер, указанный в поле Location. Поле Location дает URI прокси. Ожидается, что получатель будет повторять этот единственный запрос через прокси. 305 ответов ДОЛЖНЫ генерироваться только исходными серверами.

  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 (Не используется)

Код состояния 306 использовался в предыдущей версии спецификации, больше не используется и код зарезервирован.

10.3.8 Временное перенаправление 307

Запрошенный ресурс временно находится под другим URI. Поскольку перенаправление МОЖЕТ быть изменено при случае, клиенту СЛЕДУЕТ продолжать использовать Request-URI для будущих запросов. Этот ответ может быть кэширован, только если он указан в поле заголовка Cache-Control или Expires.

Временный URI ДОЛЖЕН быть задан в поле Location в ответе. Если метод запроса не был HEAD, объект ответа ДОЛЖЕН содержать короткую гипертекстовую заметку с гиперссылкой на новый URI, поскольку многие пользовательские агенты до HTTP / 1.1 не понимают статус 307. Следовательно, примечание ДОЛЖНО содержать информацию, необходимую пользователю, чтобы повторить исходный запрос на новом URI.

Если код состояния 307 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, при которых был выполнен запрос.

Я использую 302 сейчас, пока я не найду правильный ответ.

Обновление и заключение:

HTTP 302 лучше, поскольку, как известно, лучше всего совместим с клиентами / браузерами.

Видар Вестнес
источник
1
Я бы сказал, что совершенно обычным способом было бы вернуть 401 и страницу входа без перенаправления, но я не уверен, какие у вас есть варианты.
Ник Крейвер
1
@Nick - хороший аргумент, но я бы опасался побочных эффектов от этого, если бы создавал классическую систему входа в систему.
Пекка
1
@Pekka - Абсолютно согласен, это зависит от того, на какой платформе это происходит, и как все это может быть аккуратно обработано, также, если это интрасеть против Интернета, я считаю ... вы обычно выполняете аутентификацию по-другому в интрасети, по крайней мере, по моему опыту.
Ник Крейвер
@Nick With 401 «Ответ ДОЛЖЕН включать поле заголовка WWW-Authenticate» - как я могу объединить это с базой данных MySQL? Разве AuthType Basic и Digest не ограничены файлами конфигурации apache, такими как .htpassword и т. Д.?
Видар Вестнес
Мне нужна настраиваемая страница входа в систему, а не основной диалог браузера с запросом имени пользователя и пароля ...
Видар Вестнес,

Ответы:

66

Я бы сказал 303 см. Другие 302 Найдено:

Запрашиваемый ресурс временно находится под другим URI. Поскольку перенаправление может иногда изменяться , клиенту СЛЕДУЕТ продолжать использовать Request-URI для будущих запросов. Этот ответ кэшируется только в том случае, если он указан полем заголовка Cache-Control или Expires.

на мой взгляд, наиболее точно соответствует странице входа. Сначала я подумал, 303 see otherчто сработает так же хорошо. После некоторых размышлений я бы сказал, что 302 Foundэто более уместно, потому что запрошенный ресурс был найден, просто нужно пройти еще одну страницу, прежде чем к ней можно будет получить доступ. По умолчанию ответ не кэшируется, что тоже нормально.

Пекка
источник
4
Я согласен, но я думаю, что 302 Found указывает на то, что ресурс был найден под другим URL-адресом. Ex. Я хочу указать / my-messages / ответ сервера с 302, потому что «сегодня» мои сообщения находятся в «/ login /» (вместо «/ messages /») ... Я использую 302, но я не чувствую контекст соответствует 100%. Поскольку страница входа в систему является другим ресурсом и не имеет такого же содержания, как запрошено.
Vidar Vestnes
2
@PHP_Jedi правда. 303 может быть более подходящим с этой точки зрения. Однако 302 более надежен с точки зрения совместимости с клиентами.
Пекка
1
Да, я думаю, что 303 может лучше соответствовать контексту, поскольку в нем говорится: «Ответ на запрос можно найти под другим URI». Это говорит мне о том, что в другом URI можно найти не сам ресурс, а только ответ на этот запрос.
Vidar Vestnes
3
@PHP_Jedi Я не уверен, стоит ли тратить на это столько времени. И клиенты, и серверы в мире http в любом случае должны быть чрезвычайно либеральными и отказоустойчивыми, поэтому не будет никакой реальной разницы, используете ли вы 302или 303, за исключением того, что 302более известно. Я считаю уровень детализации достойным похвалы, и всегда хорошо делать все правильно, но слишком много усилий может быть бесполезным в этой конкретной области.
Пекка
28
К вашему сведению: Google выдает 302-е сс
Дэвид Мердок,
51

Это неправильное использование механизма перенаправления HTTP. Если пользователь не авторизован, ваше приложение должно вернуться 401 Unauthorized. Если пользователь авторизован, но не имеет доступа к запрошенному ресурсу, тогда403 Forbidden должен быть возвращен.

Вы должны сделать перенаправление на стороне клиента, например, с помощью javascript. код состояния для перенаправления, поскольку требуемая авторизация не существует . Использование 30x для этого не соответствует HTTP.

Как думать о кодах состояния HTTP, Марк Ноттингем

401 Неавторизованный запускает механизм аутентификации запроса HTTP.

401 Unauthorizedкод состояния требует наличия WWW-Authenticateзаголовка, который поддерживает различные типы аутентификации:

WWW-аутентификация: <тип> область = <область>

Bearer, OAuth, Basic, Digest, Cookie и т. Д.

filip26
источник
20
401 может не подходить в некоторых случаях, поскольку A server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header field( RFC ), и не все системы входа в систему используют этот заголовок.
starbeamrainbowlabs
6
Предположим, вы обновляете защищенную страницу; javascript на стороне клиента не будет иметь никаких изменений для вызова, и браузер отобразит всплывающее окно входа в систему вместо перенаправления пользователя на страницу входа, поэтому единственный способ - использовать код 30x.
Клод Бриссон,
2
Golang не может использовать 401 для перенаправления. Это означает, что мы должны использовать 30 * для перенаправления.
EIMEI
4
@EIMEI, следуя вашим рассуждениям, если другой язык или библиотека заставят вас использовать 401, то Интернет будет обречен. Моя точка зрения такова: то, что вы говорите, указывает на проблему с Голангом (хотя я нахожу удивительным, что у него был такой дизайн, который не позволял отправлять 401-е!)
Грег
2
@starbeamrainbowlabs В заголовке WWW-Authenticate есть черновик HTTP-аутентификации на основе файлов cookie. См .: tools.ietf.org/html/draft-broyer-http-cookie-auth-00
aef
12

Я считаю, что подходящим решением является заголовок HTTP 401 (Not Authorized).

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

Цель этого заголовка именно в этом. Но вместо перенаправления на страницу входа правильный процесс будет выглядеть примерно так:

  • Пользователь не вошел в систему, пытается получить доступ к странице с ограниченным входом.
  • система определяет, что пользователь не вошел в систему
  • система возвращает заголовок HTTP 401 И отображает форму входа в тот же ответ (не перенаправление).

Это хорошая практика, например, предоставление полезной страницы 404 со ссылками на карту сайта и формой поиска.

Увидимся.

Дэвис Пейшото
источник
20
RFC гласит: «Ответ ДОЛЖЕН включать поле заголовка WWW-Authenticate (раздел 14.46), содержащее запрос, применимый к запрошенному ресурсу». Ответ 401 действительно применим только при использовании схемы аутентификации HTTP.
bshacklett
4
В этом случае было бы лучше 403, поскольку в нем говорится, что доступ просто запрещен, а заголовок авторизации не поможет
olanod
@bshacklett WWW-Authenticate можно использовать вместе со многими схемами аутентификации (например, Bearer, OAuth). См developer.mozilla.org/en-US/docs/Web/HTTP/Headers/... и iana.org/assignments/http-authschemes/http-authschemes.xhtml
filip26
В заголовке WWW-Authenticate есть черновик HTTP-аутентификации на основе файлов cookie. См .: tools.ietf.org/html/draft-broyer-http-cookie-auth-00
aef