Правильный код статуса http для ресурса, который требует авторизации - PullRequest
56 голосов
/ 05 декабря 2011

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

Так в принципе какой код статуса будет отправлен, когда я покажу страницу входа?

Я почти уверен, что нам нужно использовать код состояния в диапазоне 4xx.

Я не говорю об аутентификации HTTP здесь, так что по крайней мере 1 код состояния мы не собираемся использовать (401 Unauthorized).

Теперь, что мы должны использовать? Ответы (также здесь на SO), кажется, различаются:

Согласно ответу здесь мы должны использовать 403 Forbidden.

Но в описании кода состояния есть:

Авторизация не поможет и запрос НЕ ДОЛЖЕН повторяться.

Ну, это не похоже на правильный. Так как авторизация БЫЛА помочь.

Итак, давайте посмотрим на какой-нибудь другой ответ. Ответ здесь даже не использует диапазон 4xx, а использует 302 Found

Описание кода статуса 302 Found:

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

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

Поэтому я пошел дальше и выбрал еще один ответ на удивление с еще одним решением.

Этот ответ предполагает, что мы выбираем 400 Bad Request.

Описание этого кода статуса:

Запрос не может быть понят сервером из-за неправильного синтаксиса. Клиент НЕ ДОЛЖЕН повторять запрос без изменений.

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

Другой ответ также говорит, что 403 ответ правильный, однако он заканчивается на:

Если это общедоступный веб-сайт, на котором вы пытаетесь запретить доступ на основе cookie-файла сеанса [это то, что я делаю], 200 с соответствующим телом, указывающим, что необходим вход в систему, или временное перенаправление 302 для входа в систему. страница часто бывает лучшей.

Так что 403 правильно, но 200 или 302 ЛУЧШИЙ.

Эй! Вот что я ищу: ЛУЧШЕЕ решение. Но не должно ли лучшее быть таким же, как правильное? И почему это будет лучшим?

Спасибо всем, кто сделал это далеко в этом вопросе:)

Я знаю, что не стоит слишком беспокоиться об этом. И я думаю, что этот вопрос более гипотетический (не совсем, но использовал его из-за отсутствия лучшего слова).

Но этот вопрос преследует меня некоторое время.

И если бы я был менеджером (который просто подобрал несколько круто звучащих слов, как они всегда делают), я бы сказал: но, но, но, но спокойствие важно. : -)

Итак: что такое the right way™ использования кода состояния в вышеуказанной ситуации (если есть)?

Т.Л., др

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

Ответы [ 8 ]

45 голосов
/ 12 декабря 2011

Если пользователь не предоставил учетных данных , и ваш API требует их, верните 401 - Unauthorized.Это вызовет клиента сделать это.Об этом конкретном сценарии обычно мало споров.

Если пользователь предоставил действительные учетные данные, но их недостаточно для доступа к запрошенному ресурсу (возможно, учетные данные были для учетной записи freemium, но запрошенного ресурсатолько для ваших платных пользователей), у вас есть несколько вариантов, учитывая слабость некоторых определений HTTP-кода:

  1. Return 403 - Forbidden.Это более наглядно и обычно понимается как «предоставленные учетные данные были действительны, но все еще недостаточны для предоставления доступа»
  2. Возврат 401 - Unauthorized.Если вы не уверены в безопасности, возможно, вы не захотите возвращать клиенту дополнительную информацию, которая была возвращена в (1) выше
  3. Вернуть либо 401, либо 403, но с полезной информацией втело ответа, описывающее причины отказа в доступе.Опять же, эта информация может быть больше, чем вы хотели бы предоставить в случае, если она несколько помогает злоумышленникам.

Лично я всегда использовал № 1 для сценария, в котором были переданы действительные учетные данные, но учетная записьу них нет доступа к запрошенному ресурсу.

26 голосов
/ 07 декабря 2011

Вы, в свою очередь, спрашиваете «лучший», «правильный путь» и «правильный», что затрудняет ответ на этот вопрос, поскольку эти критерии не обязательно являются взаимозаменяемыми и могут фактически конфликтовать, особенно еслиRESTfulness касается.

«Лучший» ответ зависит от вашей заявки.Вы создаете веб-приложение на основе простого старого браузера (POBB)?Вы создаете собственный клиент (например, iOS или Android) и запускаете сервис через Интернет?Вы интенсивно используете AJAX для обновления веб-страниц?Является ли curl предполагаемым клиентом?

Предположим, вы создаете традиционное веб-приложение.Давайте посмотрим, как Google это делает (выходные данные прерваны для краткости):

$ curl -v http://gmail.com/
< HTTP/1.1 301 Moved Permanently
< Location: http://mail.google.com/mail/
< Content-Type: text/html; charset=UTF-8
< Content-Length: 225
< ...

Google сначала перенаправляет нас на «истинный» URL для GMail (используя перенаправление 302).

$ curl -v http://mail.google.com/mail/
< HTTP/1.1 302 Moved Temporarily
< Location: https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1&ltmpl=default&ltmplcache=2
< Content-Type: text/html; charset=UTF-8
< Content-Length: 352
< ...

И затем он перенаправляет нас на страницу входа (используя перенаправление 302.)

$ curl -v 'https://accounts.google.com/ServiceLogin?service=mail&passive=true&rm=false&continue=http://mail.google.com/mail/&scc=1&ltmpl=default&ltmplcache=2'
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< ...

Сама страница входа поставляется с кодом состояния 200 !

Почему так?

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

Вы можете открыть страницу 4XX с объяснением и ссылкой на страницу входа.Это может на самом деле казаться более RESTful.Но это хуже для пользователя.

Хорошо, но есть ли случай, когда что-то вроде 403 имеет смысл?Абсолютно.

Во-первых, обратите внимание, что 403 не является четко определенным в спецификации.Чтобы понять, как это следует использовать, вам нужно посмотреть, как это реализовано в полевых условиях.

403 обычно используется веб-серверами, такими как Apache и IIS, в качестве кода состояния для страниц, возвращаемых по запросу браузерасписок каталогов (URI заканчивается на «/»), но на сервере списки каталогов отключены.В этом случае 403 действительно является специализированным 404, и вы мало что можете сделать для пользователя, кроме как сообщить ему / ей, что пошло не так.

Однако, вот пример сайта, который использует403 оба сигнализируют пользователю, что он / она не имеет достаточных привилегий и , какие действия необходимо предпринять для исправления ситуации (подробности см. В полном ответе ):

curl -v http://www.w3.org/Protocols/rfc2616/
< HTTP/1.1 403 Forbidden
< Content-Type: text/html; charset=iso-8859-1
< Content-Length: 1564
< ...

(Кроме того, 403 также встречается в веб-API, таких как API Twitter; здесь 403 означает «запрос понят, но он был отклонен. В сопроводительном сообщении об ошибке будет объяснено, почему».Этот код используется, когда запросы отклоняются из-за ограничений на обновление. ")

В качестве улучшения давайте предположим, однако, что вы не хотите перенаправлять пользователя на логинили заставьте пользователя перейти по ссылке на страницу входа.Вместо этого вы хотите отобразить форму входа на странице, которую пользователь не видит.Если они успешно аутентифицируются, они видят контент при перезагрузке страницы;если они терпят неудачу, они получают форму входа снова.Они никогда не переходят на другой URL.

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

Этот подход к аутентификации не распространен, но он может иметь смысл, и IMHO предпочтительнее pop-up-a-javascript-modal-решения для входа в систему, которые разработчики пытаются реализовать.

Вопрос сводится к вопросу, хотите ли вы перенаправить или нет?

Дополнительно: мысли о401 код состояния ...

Код состояния 401 - и связанная с ним базовая / дайджест-аутентификация - имеют много преимуществ. Он поддерживается спецификацией HTTP, поддерживается всеми крупными браузерами, по сути он не является RESTful ... Проблема в том, что с точки зрения пользовательского опыта это очень и очень непривлекательно. Это непростое, загадочное всплывающее диалоговое окно, отсутствие элегантного решения для выхода из системы и т. Д. Если вы (или ваши заинтересованные стороны / клиенты) можете смириться с этими проблемами (большое «если»), то его можно квалифицировать как «правильный». Решение.

10 голосов
/ 06 декабря 2011

Согласовано. REST - это просто стиль, а не строгий протокол. Многие публичные веб-сервисы отклоняются от этого стиля. Вы можете создать свой сервис, чтобы вернуть все, что вы хотите. Просто убедитесь, что ваши клиенты знают, какие коды возврата ожидать.

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

Я использую 400 (неверный запрос) в ответ на попытку входа с неверными учетными данными.

HTTP 302 (перемещен) кажется более подходящим для веб-приложений, где клиент является браузером. Браузеры обычно следуют за перенаправлением адреса в ответе. Это может быть полезно для направления пользователя на страницу входа.

8 голосов
/ 16 декабря 2011

Я не говорю об аутентификации HTTP здесь, так что это как минимум 1 код состояния, который мы не собираемся использовать (401 Unauthorized).

Неверно.401 является частью протокола передачи гипертекста (RFC 2616 Fielding и др.), Но не ограничивается аутентификацией HTTP.Кроме того, это единственный код состояния, указывающий, что запрос требует аутентификации пользователя.

302 и 200 кодов можно использовать , и его легче реализовать в некоторых сценариях, ноне все.И если вы хотите подчиняться спецификациям, 401 является единственным правильным ответом, который есть.

И 403 действительно самый неправильный код для возврата.Как вы правильно заявили ...

Авторизация не поможет, и запрос НЕ СЛЕДУЕТ повторять.

Так что это явно не подходит для указания того, что авторизация является опцией.

Я бы придерживался стандарта: 401 Несанкционированный

-

ОБНОВЛЕНИЕ

Добавитьнемного больше информации, устраняя путаницу, связанную с ...

Ответ ДОЛЖЕН включать поле заголовка WWW-Authenticate (раздел 14.47), содержащее запрос, применимый к запрашиваемому ресурсу.

Если вы думаете, что это помешает вам использовать 401, вы должны помнить, что есть еще:

"Значение поля состоит как минимум из одного вызова, который указывает схему (ы) аутентификации) и параметры, применимые к Request-URI. "

Это «указывает на схему (ы) аутентификации» означает, что вы можете подписаться на другие схемы авторизации!

Протокол HTTP (RFC 2616) определяет простую структуру для схем аутентификации доступа, но вы НЕ ДОЛЖНЫ использовать ЭТОТ структуру.

Другими словами: вы не связаны с обычным WWW-Auth.Вы только ДОЛЖНЫ указать, КАК ваше веб-приложение выполняет свою авторизацию, и предложить соответствующие данные в заголовке, вот и все.Согласно спецификации, используя 401, вы можете выбрать свой собственный яд авторизации!И именно здесь ваше «веб-приложение» может делать то, что ВЫ хотите, когда дело доходит до заголовка 401 и вашей реализации авторизации.

Не позволяйте спецификациям сбить вас с толку, думая, что вы ДОЛЖНЫ использовать обычную схему HTTP-аутентификации.Вы нет!Единственное, что спецификации действительно обеспечивают: вы просто ДОЛЖНЫ / ДОЛЖНЫ идентифицировать схему аутентификации вашего веб-приложения и передать связанные параметры, чтобы позволить запрашивающей стороне начать потенциальные попытки авторизации.

И если вы все еще не уверены, я могу представить все это в простой, но понятной перспективе: допустим, вы собираетесь изобрести новую схему авторизации завтра, тогда спецификации позволят вам использовать и это.Если бы спецификации ограничивали реализацию таких новых реализаций технологии авторизации, эти спецификации были бы изменены давным-давно.Спецификации определяют стандарты, но на самом деле они не ограничивают множество потенциальных реализаций.

3 голосов
/ 16 мая 2012

Как вы указали, 403 Forbidden явно определяется фразой " Авторизация не поможет ", но стоит отметить, что авторы почти наверняка ссылались здесь на HTTP-авторизацию (которая действительно будетне поможет, так как ваш сайт использует другую схему авторизации).Действительно, учитывая, что код состояния является сигналом для пользовательского агента , а не пользователя , такой код будет правильным, поскольку любая авторизация, которую пытается предоставить агент, не поможетдалее с требуемым процессом авторизации (см. 401 Unauthorized).

Однако, если вы воспринимаете это определение 403 Forbidden буквально и чувствуете, что оно все еще неуместно, возможно, 409 Conflict может подойти?Как определено в RFC 2616 §10.4.10 :

   The request could not be completed due to a conflict with the current
   state of the resource. This code is only allowed in situations where
   it is expected that the user might be able to resolve the conflict
   and resubmit the request. The response body SHOULD include enough
   information for the user to recognize the source of the conflict.
   Ideally, the response entity would include enough information for the
   user or user agent to fix the problem; however, that might not be
   possible and is not required.

Действительно, существует конфликт с текущим состоянием ресурса: ресурс находится в «заблокированном» состоянии и такой конфликтможет быть «разрешено» только через пользователя, предоставившего свои учетные данные и повторно отправившего запрос.Тело будет содержать « достаточное количество информации для пользователя, чтобы распознать источник конфликта » (оно будет указывать, что они не вошли в систему), и действительно будет также содержать « достаточное количество информации для пользователя».или пользовательский агент для решения проблемы"(т.е. форма входа в систему).

3 голосов
/ 12 декабря 2011

Ваш "TL; DR" не соответствует версии "TL".

Правильный ответ для запроса ресурса, для которого требуется авторизация, - 401.

302 не является правильным ответом, потому что, фактически, ресурс недоступен в другом месте. Первоначальный URL был верным, у клиента просто не было прав. Если вы будете следовать перенаправлению, вы на самом деле не получите то, что ищете. Вы попадаете в какой-то специальный рабочий процесс, который не имеет ничего общего с ресурсом.

403 неверно. 403 - ошибка «не могу попасть отсюда». Ты просто не видишь этого, мне все равно, кто ты. Некоторые утверждают, что 403 и 404 похожи. Разница просто в 403, сервер говорит: «Да, у меня есть, но ты не можешь», тогда как 404 говорит: «Я ничего не знаю о том, о чем ты говоришь». Обвинители в безопасности утверждают, что 404 «безопаснее». Зачем им говорить то, что им не нужно знать.

Проблема, с которой вы столкнулись, не имеет ничего общего с REST или HTTP. Ваша проблема заключается в попытке установить некие взаимосвязи между клиентом и сервером, которые в конечном итоге проявляются в каком-то файле cookie. Весь ресурс -> 302 -> Страница входа - это пользовательский интерфейс, использующий хак, известный как веб-браузер, который в своей обычной форме представляет собой паршивого HTTP-клиента и паршивого участника REST.

HTTP имеет механизм авторизации. Заголовок авторизации. Пользовательский опыт в общем браузере ужасен. Так что никто не использует это.

Так что нет правильного HTTP-ответа (да, 401, но не / не могу его использовать). Нет правильного ответа REST, поскольку REST обычно полагается на базовый протокол (в данном случае HTTP, но мы уже рассмотрели это).

Итак. 302 -> 200 для страницы входа - это все, что она написала. Вот что ты получаешь. Если вы не используете браузер или сделали все через XHR или какой-либо другой пользовательский клиент, это не будет проблемой. Вы бы просто использовали заголовок авторизации, следовали протоколу HTTP и использовали схему, подобную DIGEST или тому, что использует AWS, и все готово. Затем вы можете использовать соответствующие стандарты для ответа на подобные вопросы.

0 голосов
/ 22 июня 2017

Я полагаю, что 401 - это правильный код состояния для возврата из-за неудачной авторизации. Ссылка RFC 2616, раздел 14,8 На нем написано «Пользовательский агент, который хочет аутентифицировать себя на сервере - обычно, но не обязательно, после получения ответа 401 »

0 голосов
/ 16 декабря 2011

Ваш ответ:

401 Unauthorized особенно, если вам все равно или вы не будете перенаправлять людей на страницу входа

-или-

302 Found, чтобы подразумевать, что ресурс был, но они должны предоставить учетные данные, которые будут ему возвращены. Делайте это только в том случае, если вы будете использовать перенаправление и не забудьте предоставить соответствующую информацию в теле ответа.


Другие предложения:

401 Unauthorized обычно используется для ресурсов, к которым пользователь не имеет доступа после обработки аутентификации.

403 Forbidden немного неясен для меня честно. Я использую его, когда блокирую ресурсы на уровне файловой системы, и, как сказано в вашем посте, «авторизация не помогает».

400 Bad Request неуместно, так как необходимость входа в систему не соответствует неправильному синтаксису.

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