REST и варианты аутентификации - PullRequest
69 голосов
/ 19 января 2009

В настоящее время я работаю над библиотекой REST для .net, и мне хотелось бы услышать некоторые мнения о моей открытой точке зрения: REST и аутентификация.

Вот пример интерфейса RESTful, используемого с библиотекой:

[RestRoot("/user")]
public interface IUserInterface
{
  [RestPut("/")]
  void Add(User user);

  [RestGet("/")]
  int[] List();

  [RestGet("/get/{id}")]
  User Get(int id);

  [RestDelete("/delete/{id}")]
  void Delete(int id);
}

Серверный код затем просто реализует интерфейс, и клиенты могут получить тот же интерфейс через фабрику. Или, если клиент не использует библиотеку, также работает стандартный HTTP-запрос.

Я знаю, что существуют основные способы использования HTTP Basic Auth или отправки токена на запросы, требующие аутентифицированных пользователей.

Первый метод (HTTP Basic Auth) имеет следующие проблемы (частично относящиеся к веб-браузеру):

  • Пароль передается с каждым запросом - даже с SSL это вызывает «плохое предчувствие».
  • Поскольку пароль передается с заголовком запроса, локальному злоумышленнику будет легко просмотреть переданные заголовки, чтобы получить пароль.
  • Пароль доступен в памяти браузера.
  • Нет стандартного способа истечения срока действия пользовательских "сессий".
  • Вход в систему с помощью браузера прерывает внешний вид страницы.

Проблемы для второго метода более сфокусированы на реализации и использовании библиотеки:

  • Каждый URI запроса, который требует аутентификации, должен иметь параметр для токена, который просто очень повторяется.
  • Нужно написать намного больше кода, если каждая реализация метода должна проверить, является ли токен действительным.
  • Интерфейс станет менее специфичным, например, [RestGet("/get/{id}")] против [RestGet("/get/{id}/{token}")].
  • Где поставить токен: в конце URI? после рута? где-то еще?

Моя идея состояла в том, чтобы передать токен в качестве параметра URL-адресу, например http:/server/user/get/1234?token=token_id.

Другой возможностью было бы отправить параметр в виде заголовка HTTP, но это, я думаю, усложнило бы использование с простыми клиентами HTTP.

Маркер будет передаваться клиенту в виде настраиваемого HTTP-заголовка ("X-Session-Id") при каждом запросе.

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

Как вы думаете, это слишком сильно нарушит REST или у вас есть идеи получше?

Ответы [ 3 ]

64 голосов
/ 21 января 2009

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

Похоже, вы ориентируетесь на веб-браузеры в качестве клиента? Если это так, вы можете исследовать, используя аутентификацию доступа к дайджесту HTTP или выдавая клиентам свои собственные сертификаты SSL для уникальной идентификации и аутентификации. Кроме того, я не думаю, что сессионные куки-файлы - это обязательно плохо. Особенно когда приходится иметь дело с браузером. До тех пор, пока вы изолируете код обработки куки-файлов и сделаете так, чтобы остальная часть приложения не использовала его, у вас все будет хорошо. Ключ только хранить личность пользователя в сеансе, ничего больше. Не злоупотребляйте состоянием сеанса на стороне сервера.

Если вы нацеливаетесь не на браузер, а на других клиентов, вы можете воспользоваться несколькими подходами. Мне повезло с использованием механизма аутентификации S3 Amazon .

Это все очень субъективно, конечно. Чистота и следование REST к письму иногда могут быть непрактичными. Пока вы минимизируете и изолируете такое поведение, ядро ​​вашего приложения все еще может быть RESTful. Я настоятельно рекомендую RESTful Web Services как отличный источник информации и подходов к REST.

15 голосов
/ 21 января 2009

Я согласен с workmad3, если необходимо поддерживать время жизни сессии, вам следует создать ресурс сессии. Запись на этом ресурсе с учетными данными пользователя (обычная аутентификация или учетные данные в содержании тела) будет возвращать уникальный идентификатор сеанса. Удалить on / session / {id} выйдет из системы.

Если вы хотите контролировать время истечения сеанса. При создании нового сеанса (публикация на ресурсе сеанса) сервер будет устанавливать cookie в ответе (используя стандартный заголовок set-cookie). Файл cookie будет содержать время истечения. Строка cookie должна быть зашифрована на сервере, поэтому только сервер может открыть этот cookie. Каждый последующий запрос к серверу отправляет файл cookie сеанса в заголовок файла cookie. (это будет сделано автоматически для вас, если ваш клиент является браузером). Серверу необходимо «обновлять» cookie для каждого запроса, то есть создавать новый cookie с новым временем истечения (увеличить время ожидания сеанса). Не забудьте очистить cookie, когда пользователь вызывает delete на ресурсе сеанса.

Если вы хотите, чтобы ваше приложение было более защищенным, вы можете сохранить IP-адрес клиента в самом файле cookie, чтобы при получении запроса сервер мог проверить, что оно было отправлено с «оригинального» клиента. Но помните, что это решение может быть проблематичным, когда задействованы прокси, потому что сервер может «видеть» все запросы, поступающие от одного и того же клиента.

4 голосов
/ 19 января 2009

Остальная аутентификация, которую я видел, рассматривает сессии как ресурс REST для создания, уничтожения и т. Д., А затем идентификатор сессии передается туда и обратно. Те, что я видел, обычно используют для этого куки-файл сессии, поскольку это единственный способ обеспечить его безопасность. Если вы передадите идентификатор сеанса в URL, у вас не будет способа действительно аутентифицировать его, полученный от правильного клиента.

Аутентификация - это непростая проблема с REST, поскольку она требует, чтобы некоторая форма состояния оставалась вне URL, что нарушает принципы REST, когда URL является всем, что требуется для представления состояния.

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