Защита REST API без необходимости изобретать колесо

При разработке REST API обычно используется аутентификация пользователя в первую очередь?

Типичный пример использования, который я ищу, это:

  • Пользователь хочет получить данные. Конечно здорово, что мы хотели бы поделиться! Получить общедоступный ключ API и прочесть!
  • Пользователь хочет хранить/обновлять данные... woah wait up! кто вы, можете ли вы это сделать?

Я хотел бы создать его один раз и разрешить использовать веб-приложение, приложение для Android и приложение для iPhone.

API REST представляется логичным выбором с такими требованиями, как

Чтобы проиллюстрировать мой вопрос, я буду использовать простой пример.

У меня есть элемент в базе данных, который имеет атрибут рейтинг (целое число от 1 до 5).

Если я правильно понял REST, я бы выполнил запрос GET, используя язык по своему выбору, который возвращает csv, xml или json следующим образом:

http://example.com/product/getrating/{id}/

Скажем, мы выбираем JSON, который мы возвращаем:

{
  "id": "1",
  "name": "widget1",
  "attributes": { "rating": {"type":"int", "value":4} }
}

Это отлично подходит для API, ориентированных на пользователей. Я получаю эту часть.

Где у меня есть вопрос, как я могу объединить это с моделью безопасности? Я привык к безопасности веб-приложений, где у меня есть состояние сеанса, которое идентифицирует моего пользователя в любое время, поэтому я могу контролировать, что они могут делать независимо от того, что они решили отправить мне. Насколько я понимаю, это не RESTful, поэтому было бы плохим решением в этом случае.

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

Если пользователь "JOE" хочет добавить рейтинг в элемент

Это можно сделать, используя:

http://example.com/product/addrating/{id}/{givenRating}/

В этот момент я хочу сохранить данные, говорящие, что "JOE" дал продукт {id} рейтинг {givenRating}.

Вопрос: Как узнать, что запрос пришел из "JOE" , а не "BOB".

Кроме того, что, если это было для более разумных данных, таких как номер телефона пользователя?

То, что у меня есть до сих пор:

1) Используйте встроенную функцию HTTP для аутентификации при каждом запросе, либо в обычном HTTP, либо в HTTPS.

Это означает, что каждый запрос теперь принимает форму:

https://joe:[email protected]/product/addrating/{id}/{givenRating}/

2) Используйте такой подход, как Amazon S3 с закрытым и открытым ключом: http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

3) В любом случае используйте файл cookie и разбивайте аганированную часть REST.

Второй подход кажется мне лучше, но мне остается интересно, действительно ли мне нужно изобретать все это? Хеширование, хранение, создание ключей и т.д. Все отдельно?

Это очень похоже на использование сеанса в типичном веб-приложении и переписывание всего стека самостоятельно, что обычно для меня означает "вы делаете это неправильно", особенно при работе с безопасностью.

EDIT: Думаю, я должен был упомянуть OAuth.

Ответ 1

Редактировать 5 лет спустя

Используйте OAuth2!

Предыдущая версия

Нет, нет необходимости использовать cookie. Это не так безопасно, как HTTP Digest, OAuth или Amazon AWS (который не сложно скопировать).

То, как вы должны смотреть на файл cookie, - это токен аутентификации, а также Basic/Digest/OAuth/какой бы он ни был, но менее подходящий.

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

Печеньки злы, перестают их использовать.

Ответ 2

Не беспокойтесь о том, чтобы быть "RESTful", беспокоиться о безопасности. Вот как я это делаю:

Шаг 1: Пользователь выполняет проверку подлинности с учетными данными.

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

Шаг 3: добавьте вызов точки входа в начало каждой веб-службы script, которая проверяет идентификатор отпечатка и идентификатор сеанса для каждого запроса веб-службы.

Шаг 4: Если идентификатор отпечатка пальца и идентификатор сеанса недействительны или имеют тайм-аут, перенаправление на аутентификацию.

ПРОЧИТАЙТЕ ЭТО:

Аутентификация RESTful

Ответ 3

Редактировать 3 года спустя

Я полностью согласен с Evert, используйте OAuth2 с HTTPS и не изобретайте колесо!:-)

Более простые API REST - не предназначенные для сторонних клиентов - JSON Web Tokens могут быть хорошими.

Предыдущая версия

Использовать файл cookie в любом случае и разбить часть без сохранения состояния REST.

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

Таким образом, клиент REST должен хранить коэффициенты идентификации и отправлять их с каждым запросом. Не путайте клиент REST с клиентом HTTP. Они не одинаковы. Клиент REST также может быть на стороне сервера, если он использует завиток, или он может создать, например, только HTTP файл cookie на стороне сервера, который он может предоставить службе REST через CORS. Единственное, что имеет значение для службы REST для аутентификации по каждому запросу, поэтому вам нужно отправить учетные данные (имя пользователя, пароль) с каждым запросом.

  • Если вы пишете клиент REST на стороне клиента, это можно сделать с помощью SSL + HTTP auth. В этом случае вы можете создать кеш credentials -> (identity, permissions) на сервере, чтобы ускорить аутентификацию. Имейте в виду, что если вы очистите этот кеш, и пользователи отправят один и тот же запрос, они получат тот же ответ, просто он займет немного больше времени. Вы можете сравнить это с сеансами: если вы очистите хранилище сеансов, тогда пользователи получат ответ status: 401 unauthorized...
  • Если вы пишете клиент REST на стороне сервера и отправляете идентификационные факторы службе REST через curl, у вас есть 2 варианта. Вы также можете использовать http auth, или вы можете использовать диспетчер сеанса в своем клиенте REST, но не в службе REST.
  • Если кто-то не доверяет, пишет ваш клиент REST, вам нужно написать приложение для аутентификации пользователей и предоставить им доступность, чтобы решить, хотят ли они предоставлять разрешения для разных клиентов или нет. Oauth - это уже существующее решение для этого. Oauth1 более безопасен, oauth2 менее безопасен, но проще, и, я думаю, есть несколько других решений для этой проблемы... Вам не нужно изобретать это. Существуют полные решения для авторизации и авторизации с использованием oauth, например: wso-сервер идентификации.

Печенье не обязательно плохое. Вы можете использовать их RESTful, пока они не будут содержать состояние клиента, а служба содержит только состояние ресурса. Например, вы можете сохранить корзину или предпочтительные параметры разбивки на страницы в файлах cookie...