Шаблон входа REST API

181

Я создаю REST API, внимательно следуя советам Apigee, используя существительные, а не глаголы, версию API, запеченную в URL, два пути API для каждой коллекции, использование GET POST PUT DELETE и т. Д.

Я работаю над системой входа в систему, но не уверен в правильном способе REST для входа пользователей. Я не работаю над безопасностью на данный момент, просто шаблон входа или поток. (Позже мы будем добавлять 2 шага oAuth с HMAC и т. Д.)

Возможные варианты

  • ПОЧТА что-то вроде https://api...com/v1/login.json
  • Положить на что-то вроде https://api...com/v1/users.json
  • Что-то у меня нет, хотя ...

Каков правильный стиль REST для входа в систему пользователей?

Скотт Рипнак
источник
9
Это формат ответа. .json указывает серверу ответить json, .xml говорит серверу ответить в формате xml. Скорее это делает его необязательным параметром за? blog.apigee.com/detail/…
Скотт Рёпнак
28
Никогда не видел согласование контента, выполненное по URL, только в заголовках. На URL это означает, что вы теряете преимущества кэширования и многое другое.
Одед
10
@ScottRoepnack, тогда вы должны рассмотреть Acceptзаголовок HTTP.
Алессандро Вендрусколо
2
@Oded Если бы вы использовали Acceptзаголовок, у вас также был бы Vary: Accept, поэтому кеширование не пострадает. Conneg в расширении обсуждался ранее ; Я бы согласился с ответом Shonzilla там, хотя.
cmbuckley
2
@ Одед - я не понимаю. почему вы потеряете преимущество кэширования, если вы укажете тип содержимого в URL (либо в виде суффикса .json к пути запроса, либо в качестве параметра запроса type = json)? И кто такой «ты» в этом случае? Кто тот человек, который теряет преимущества кэширования? мне кажется, что результаты любого запроса могут быть кэшированы независимо от того, что находится в пути или параметрах запроса.
Cheeso

Ответы:

138

Принципиальное проектирование современной веб-архитектуры Роя Т. Филдинга и Ричарда Н. Тейлора , т. Е. Последовательность работ из всей терминологии REST, содержит определение взаимодействия клиент-сервер:

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

Это ограничение выполняет четыре функции, 1-я и 3-я важны в данном конкретном случае:

  • 1-й : устраняет необходимость в соединителях для сохранения состояния приложения между запросами , что снижает потребление физических ресурсов и повышает масштабируемость;
  • 3-й : он позволяет посреднику просматривать и понимать запрос изолированно , что может быть необходимо при динамической реорганизации сервисов;

А теперь давайте вернемся к вашему делу безопасности. Каждый запрос должен содержать всю необходимую информацию, и авторизация / аутентификация не является исключением. Как этого добиться? Буквально отправляйте всю необходимую информацию по проводам с каждым запросом.

Одним из примеров того, как это можно заархивировать, является код аутентификации сообщений на основе хэша или HMAC . На практике это означает добавление хеш-кода текущего сообщения к каждому запросу. Хеш-код, рассчитанный с помощью криптографической хеш-функции в сочетании с секретным криптографическим ключом . Криптографическая хеш-функция либо предопределена, либо является частью концепции REST кода по требованию (например, JavaScript). Секретный криптографический ключ должен быть предоставлен сервером клиенту в качестве ресурса, и клиент использует его для вычисления хеш-кода для каждого запроса.

Есть много примеров реализации HMAC , но я бы хотел, чтобы вы обратили внимание на следующие три:

Как это работает на практике

Если клиент знает секретный ключ, он готов работать с ресурсами. В противном случае он будет временно перенаправлен (код состояния 307 Temporary Redirect) для авторизации и получения секретного ключа, а затем перенаправлен обратно на исходный ресурс. В этом случае нет необходимости заранее знать (т. Е. Где-то жестко), какой URL-адрес для авторизации клиента , и можно со временем изменить эту схему.

Надеюсь, что это поможет вам найти правильное решение!

Аким
источник
23
MAC предназначен для проверки подлинности сообщений и защиты от подделки - он не имеет ничего общего с аутентификацией пользователя
yrk 26.12.12
1
Добавлен один из примеров того, как обрабатывать аутентификацию пользователя / клиента, не зная заранее « URL-адрес входа »
Аким
Вот еще две замечательные статьи с примерами аутентификации без сохранения состояния для служб REST: blog.jdriven.com/2014/10/… technicalrex.com/2015/02/20/…
Владимир Рожков
41

TL; DR Логин для каждого запроса не является обязательным компонентом для реализации безопасности API, аутентификация есть.

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

REST не предписывает никаких правил безопасности, но наиболее распространенной практической реализацией является OAuth с трехсторонней аутентификацией (как вы упомянули в своем вопросе). Сам по себе вход в систему отсутствует, по крайней мере, не для каждого запроса API. При трехсторонней аутентификации вы просто используете токены.

  1. Пользователь утверждает клиент API и разрешает делать запросы в виде долгоживущего токена
  2. Клиент Api получает недолговечный токен, используя долгоживущий.
  3. Api клиент отправляет недолговечный токен с каждым запросом.

Эта схема дает пользователю возможность аннулировать доступ в любое время. Практически все общедоступные API RESTful, которые я видел, используют OAuth для реализации этого.

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

Для получения дополнительной информации об аутентификации REST API в целом вы можете обратиться к следующим ресурсам:

Славо
источник
Да, Ой! Очень простой ответ, должен быть принятый ответ, imho.
Левит
26

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

Экраны входа в систему отлично подходят для случаев использования пользователем: зайдите на экран входа в систему, введите имя пользователя и пароль, установите cookie, клиент предоставляет этот cookie во всех будущих запросах. Нельзя ожидать, что люди, использующие веб-браузеры, будут предоставлять идентификатор пользователя и пароль при каждом отдельном HTTP-запросе.

Но для REST API экран входа в систему и сеансовые куки не являются строго необходимыми, поскольку каждый запрос может включать учетные данные, не влияя на пользователя; и если клиент не сотрудничает в любое время, 401может быть дан «несанкционированный» ответ. RFC 2617 описывает поддержку аутентификации в HTTP.

TLS (HTTPS) также может быть опцией, и он позволит аутентифицировать клиента на сервере (и наоборот) при каждом запросе путем проверки открытого ключа другой стороны. Кроме того, это обеспечивает канал для бонуса. Конечно, обмен парой ключей перед связью необходим для этого. (Обратите внимание, что речь идет именно об идентификации / аутентификации пользователя с помощью TLS. Защита канала с помощью TLS / Diffie-Hellman всегда хорошая идея, даже если вы не идентифицируете пользователя по его открытому ключу.)

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

wberry
источник
1
«поскольку каждый запрос может включать учетные данные, не влияющие на пользователя», были изобретены 3-сторонняя аутентификация и OAuth, потому что в кавычках все плохо. Если вы предоставляете учетные данные для каждого запроса без механизма их отзыва на сервере, это будет небезопасно, если используется без SSL.
Славо
1
Всякий раз, когда существует концепция пользователей, что-то должно передаваться от клиента к серверу, чтобы определить, какого пользователя. Токен OAuth, безусловно, может служить здесь в качестве «учетных данных» вместо фактической комбинации пользователя и пароля. Защита канала с помощью TLS - это, конечно, всегда хорошо, но это почти не имеет значения. Даже если вы используете cookie, какой-то токен все равно отправляется на сервер с каждым запросом, только с заголовком cookie вместо заголовка аутентификации.
wberry
И если по какой-либо причине вы не используете TLS или OAuth, действительно ли отправка пользователя / пароля каждый раз действительно хуже, чем отправка его только один раз? Если злоумышленник может получить имя пользователя / пароль, злоумышленник может также получить cookie-файл сеанса.
wberry 19.12.12
Различие между cookie-файлом и аутентификационным заголовком в качестве учетных данных заключается в том, что cookie-файлы всегда связаны с конкретным доменом. Это означает, что когда API получает cookie-файл, он знает, откуда он пришел (был написан тем же доменом ранее). С заголовком вы никогда не узнаете, и для этого вам нужно выполнить определенные проверки. В целом я согласен, они оба являются учетными данными, но я думаю, что передача учетных данных не является логином. Вход в систему - это активное действие по открытию двери. В случае трехсторонней аутентификации только первое одобрение клиента будет логином.
Славо