2010-10-28 3 views
30

Вдохновленный мыслью, глядя на вопрос «Correct HTTP status code when resource is available but not accessible because of permissions», я буду использовать тот же сценарий, чтобы проиллюстрировать мой гипотетический вопрос.Можно ли вернуть HTTP 401 для несуществующего ресурса вместо 404, чтобы предотвратить раскрытие информации?

Представьте, что я создаю веб-сервис с автопокрытием.

Предположим следующее

GET /api/persons/angela/location 

возвращает текущее положение пользователя "Анджела". Только сама ангелочка и возможный водитель, который собирается ее забрать, должны знать ее местоположение, поэтому, если запрос не аутентифицирован соответствующему пользователю, возвращается ответ 401 Unauthorized.

рассмотреть также просьбу

GET /api/persons/john/location 

, когда ни один пользователь по имени Джон не зарегистрирован в системе. Нет ресурса john, не говоря уже о ресурсе для местоположения john, поэтому это, очевидно, возвращает 404 Not Found. Или это?

Что делать, если я не хочу раскрывать, зарегистрирован ли john в системе?

(Возможно, имена пользователей взяты из небольшого пула университетских логинов, и в кампусе есть очень воинственная группа по велоспорту, которая принимает очень тусклый взгляд на использование автомобиля, даже если вы собираете? URL для каждого пользователя, и если они получат 401 вместо 404, сделайте вывод, что пользователь является автоматом)

Имеет смысл вернуть 401 Unauthorized для этого запроса, хотя ресурс не существует и существует невозможно установить набор учетных данных, которые могут быть предоставлены в запросе, чтобы сервер возвращал 200?

+1

+1 для правильного использования «infer» (и для интересного вопроса). –

+0

Некоторые изобретательные решения здесь и некоторые интересные обсуждения. Всем спасибо. – Day

+1

+1 для воинствующего велосипедного лобби. Я должен присоединиться к моему местному отделению! –

ответ

23

На самом деле, W3C recommends (RFC 2616 §10.4.4 403 Запрещено) делает обратное. Если кто-то пытается получить доступ к ресурсу, но не имеет надлежащей аутентификации, верните 404, а не 403 (Запрещено). Это все еще решает проблему раскрытия информации.

Если сервер не желает, чтобы сделать эту информацию доступной для клиента , код состояния 404 (Не Found) может быть использован вместо.

Таким образом, вы никогда не вернетесь 403 (или 401). Однако, я думаю, ваше решение также разумно.

EDIT: Я думаю, что Гейбе на правильном пути. Вам придется пересмотреть часть дизайна, но почему бы не:

  • Не найдено - 404
  • пользователя конкретным недостаточное разрешение - 404
  • Общее недостаточное разрешение (никто не может получить доступ) - 403
  • не вошли - 401
+0

Для 403 это правда, но мой гипотетический API возвращает 401, чтобы бросить вызов клиенту учетных данных. 403 используется для ресурсов, которые не могут быть просмотрены кем-либо, независимо от предоставленных учетных данных. – Day

+1

День: вы возвращаете 401, если клиент не аутентифицирован; 404, если пользователь аутентифицирован, но не имеет доступа к ресурсу. – Gabe

+0

@Gabe: Я вижу, это должно сработать. Я думаю, что ответ нуждается в редактировании, чтобы сделать все более четким. – Day

1

Я думаю, что это нормально, если вы хотите вернуть 401 Несанкционированное если запрос сделан клиентом, который не является пользователем.Однако, если пользователь делает запрос и проходит проверку подлинности, то я не думаю, что оптимальным решением является 401. Если вы считаете, что возвращение 404 может поставить под угрозу безопасность некоторых пользователей, то вы можете захотеть вернуть 403 Forbidden или, возможно, 200 OK, но просто не указывайте местоположение. Если я запрошу для пользователя bob и получить ответ и запрос для пользователя sam и получить ответ об ошибке, будь то 401, 403, 404 и т. Д., То я, вероятно, могу прийти к выводу, что это означает, что пользовательский sam не существует.

200 OK без указания местоположения может быть самым замаскированным решением.

Редактировать: Просто для иллюстрации того, что я предлагаю. Верните 401, если клиент не авторизовался. В противном случае всегда возвращайте 200 OK.

<user-location for="bob"> 
    <location>geo-coordinates here</location> 
</user-location> 

<user-location for="sam"> 
    <location/> 
</user-location> 

Это не означает, что существует сам sam или нет, или, возможно, в нем нет данных о местоположении.

+0

Но он обеспокоен даже раскрытием существования определенного пользователя с помощью этого метода; возвращение чего-либо другого вообще дало бы эту информацию. –

+0

Не обязательно. Он может просто указать, что для пользователя нет текущих данных локации. Я разъяснил это в своем ответе. –

+0

@Steven. Интересное решение, но что-то не совсем понятно. Я думаю, что у нас возникают проблемы, если мы будем действовать так, как если бы запросы были аутентифицированы, когда они на самом деле нет. Возврат поддельного пустого места, если запрашивающий не аутентифицирован, а не 401 означает, что, например, eric, который зарегистрирован и имеет разрешение на просмотр местоположения Сэма (потому что сам принимал eric как потенциальный драйвер) может ошибочно ошибочно использовать его учетные данные и не осознавать, потому что он получает ответ 200, и поэтому отказывается от мысли, что sam сейчас не имеет места. – Day

1

Я думаю, что лучшим решением было бы вернуть 403 (запрещено) для каждой (потенциальной) страницы в классе, если пользователь не прошел аутентификацию, чтобы увидеть любой из них. Если пользователь, верните 404 для вещей, которых там нет, и 200 для вещей, которые есть.

+1

Но, скорее всего, это будет не так сложно или дорогостоящим, чтобы зарегистрироваться как автомобиль. Таким образом, вы по-прежнему эффективно предоставляете информацию всем. –

+0

@Matthew Flaschen точно так, это проблема с этим решением. Спасибо за предложение, хотя – Day

+0

Правда. Я предполагаю, что можно избежать этого, чтобы не брать имена пользователей с адресов электронной почты? И, видимо, я не получил различие между 403 и 401. Oops ... – SamB

1

401 Unauthorized В любом случае, когда пользователю не разрешено видеть конкретную страницу, существует ли она или нет.

От RFC 2616: «Если запрос уже включен в учетные данные авторизации, то ответ 401 указывает, что для этих учетных данных было отказано в авторизации».

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

Кроме того, описание 403 Forbidden включает в себя: «Авторизация не поможет, и запрос НЕ ДОЛЖЕН повторяться». В отличие от этого, если пользователь выбирает для входа в систему с использованием соответствующих учетных данных, авторизация будет справка.

+0

Я не уверен, что я следую за файлом .htpasswd здесь. Вероятно, лучше всего попытаться объяснить в общих терминах HTTP, не обсуждая детали реализации сервера? – Day

+0

.htpasswd - это списки действительных учетных данных для определенного URL-адреса или URL-адресов. Они используются веб-сервером Apache и ссылаются на конкретные директивы конфигурации, которые указывают серверу требовать аутентификации для определенных URL-адресов. – PleaseStand

8

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

Hackable urls отлично подходит для информации, которую вы хотите, чтобы каждый мог легко получить доступ. Однако для клиента RESTful нет проблем с использованием URI, которые полностью непрозрачны.

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

+2

+1 для некоторого бокового мышления. URL-адреса даже не должны быть непрозрачными, просто скройте имя пользователя. например '/ api/persons//location'. Все еще читаемый, '' присваивается имени пользователя при их регистрации, и это сопоставление хранится в частной системе системой, но имена пользователей по-прежнему используются в ресурсах и могут быть видны аутентифицированным пользователям, которым были предоставлены соответствующие разрешения. Это нормально для возврата 401 для '/ api/persons/1/location', когда реквестер не аутентифицирован и 404 для'/api/persons/3/location', потому что это не показывает имя пользователя зарегистрированного лица с id = 1. – Day

+0

Я предполагаю, что недостатком может быть то, что это добавляет слой косвенности, что добавляет сложности и может иметь значительные последствия для хранилища, если у вас есть большой набор ресурсов, которым необходимо назначать непрозрачные дескрипторы, только для использования в URL-адресах. – Day

+0

@Day дополнительный уровень косвенности, который, безусловно, является тем, как должны работать службы REST. Вы только начинаете с корневого URL-адреса, все другие URL-адреса, которые использует клиент, должны быть обнаружены с сервера.Что касается хранилища, я действительно не покупаю это. Хранение дополнительного int или даже большого int, если у вас есть великие видения, для каждой учетной записи пользователя тривиально. –

 Смежные вопросы

  • Нет связанных вопросов^_^