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

Варианты REST и аутентификации

В настоящее время я работаю над библиотекой 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);
}

Затем код сервера просто реализует интерфейс, и клиенты могут получить один и тот же интерфейс через factory. Или, если клиент не использует библиотеку, также работает стандартный 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 или у вас есть идеи?

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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