Подтвердить что ты не робот

Правильный код состояния http для ресурса, который требует авторизации

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

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

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

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

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

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

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

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

Ну, это не похоже на правильное. Поскольку авторизация ДОЛЖНА помочь.

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

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

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

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

Итак, я продвинулся и выбрал еще один answer с еще одним решением.

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

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

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

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

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

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

Итак, 403 является правильным, но 200 или 302 является ЛУЧШИМ.

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

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

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

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

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

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

TL;DR

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

Предположим, вы создаете традиционное веб-приложение. Посмотрите, как 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 для всплывающих-javascript-модальных для входа решений, которые разработчики пытаются реализовать.

Это доходит до вопроса, хотите ли вы перенаправить или нет?

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

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

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

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

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

-

UPDATE

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

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

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

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

Это "указание схемы (ов) аутентификации" означает, что вы можете выбрать другой аут-схемы!

Протокол HTTP (RFC 2616) определяет простую структуру для схем аутентификации доступа, но вы не должны использовать инфраструктуру THAT.

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

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

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

Ответ 5

Ваш "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, и выполняются. Затем вы можете использовать соответствующие стандарты для ответа на такие вопросы.

Ответ 6

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

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

Ответ 7

Ваш ответ:

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

-or-

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


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

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

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

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

Ответ 8

Я считаю, что 401 - это правильный код состояния для возврата из неудавшейся авторизации. Ссылка RFC 2616 раздел-14.8 Он читает "Пользовательский агент, который хочет аутентифицироваться на сервере - обычно, но не обязательно, после получения ответа 401