Проектирование конечных точек RESTful API с фильтрацией и авторизацией

#rest #authorization #uri #endpoints

#rest #авторизация #uri #конечные точки

Вопрос:

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

Сбор всех документов по списку GET — list — только для администратора.:

/api/документы

Получение списка сбора всех документов — любой пользователь, имеющий доступ к документу 123

/api/документы/123

Поэтому для обычных пользователей конечные точки должны быть

список всех документов для пользователя 12

/api/user/12/documents

документ 123 предполагает, что пользователь 12 имеет доступ

/api/документы/123

ИЛИ … должны ли конечные точки быть такими, как показано ниже, и использоваться фильтр строки запроса:

/api/documents?пользователь=12

/api/документы/123

Ответ №1:

В этом случае вам сойдет с рук всего две конечные точки (и один заголовок!). Убедитесь, что API for /documents возвращает Vary: Authorization заголовок. Затем вы можете использовать

 GET /api/documents              // return all docs the logged-in user can see
GET /api/documents?userId=bob   // return all of bob's docs that the logged-in user can see
GET /api/documents/123          // return doc 123 if the logged-in user can see it    
 

Не совсем неразумно вкладывать пользователя a la GET /api/users/bob/documents . Я считаю, что конечным пользователям сложнее изучать API с большим количеством конечных точек, и я чувствую, что вложенный подход имеет тенденцию создавать много конечных точек. Концептуально проще перейти /documents и посмотреть, что вы можете отфильтровать, а не смотреть на каждую конечную точку и видеть, какие фильтры у нее есть.

Комментарии:

1. Спасибо — хотя, насколько я понимаю, данная конечная точка всегда должна возвращать одни и те же результаты, независимо от разрешений. Итак,. GET /api/documents вернет все документы, несмотря ни на что. Если пользователь с более ограниченной ролью получает к этому доступ, он должен получить 403 и использовать другую конечную точку.

2. @JohnRoyal В этом и заключается цель Vary: Authorization заголовка. Это позволяет всем заинтересованным сторонам знать, что результаты будут варьироваться в зависимости от учетных данных пользователя. Это хорошо, но не всегда практично, когда конечная точка не зависит от пользователя. Конечно, HTTP не был разработан с учетом этого в качестве предполагаемого ограничения, иначе не было бы заголовка Vary: Authorization!

3. @JohnRoyal Что, если я попытаюсь ПОМЕСТИТЬ в /documents/123, когда у меня нет доступа на запись? Я могу читать, но не изменять его. Однако автор может как ПОЛУЧИТЬ, так и ПОМЕСТИТЬ в этот документ. Один и тот же URI, разные результаты, когда разные пользователи выполняют один и тот же вызов. Я не вижу принципиальной разницы между этим случаем и получением, возвращающим разные результаты на основе аутентификации.

4. Теперь я понимаю. Спасибо

Ответ №2:

Я бы полностью разделил бизнес-логику и логику авторизации. Если вы хотите получить документ XYZ, вы не будете передавать идентификатор пользователя в качестве параметра HTTP.

Вы предложили /api/documents?user=12 , но на самом деле это должно быть просто /api/documents . Информация о пользователе должна поступать с уровня аутентификации.

Аналогично, авторизация должна быть полностью отдельной. Причины этого:

  • разделение проблем
  • возможность обновлять логику авторизации независимо от бизнес-логики
  • избегайте влияния на дизайн API

API должен отражать только те бизнес-объекты, о которых вы заботитесь, например, документы в этом случае (возможно, также пользователи, если вы хотите отобразить профиль пользователя …).

Для обработки аутентификации используйте стандартные методы контейнера (например, базовую аутентификацию HTTP) или используйте расширенные методы аутентификации (OAuth ..) через выделенную платформу.

Для обработки авторизации используйте фильтр, перехватчик. В мире Java (где JAX-RS реализует REST) взгляните на перехватчики и фильтры Джерси. Затем вы хотите, чтобы перехватчик (или точка принудительного применения политики — PEP) запрашивал внешнюю службу авторизации (или точку принятия решений о политике).

Защита архитектуры REST API

Подробнее ознакомьтесь с ABAC, моделью управления доступом на основе атрибутов, и XACML, расширяемым языком разметки управления доступом, которые объясняют, как управлять доступом к вашим API REST, не смешивая бизнес-логику и логику авторизации.