Несколько уровней авторизации, а не только на основе ролей

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

1) Ролевая авторизация

У нас есть четко определенные роли, где каждая роль имеет доступ к набору ресурсов, а разные роли могут обращаться к тем же ресурсам.

Ресурсы на данный момент представляют собой просто действия MVC, отображаемые в таблице базы данных как module, controller и action.

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

2) Пользовательское разрешение

Помимо авторизации на основе ролей пользователи могут иметь более или менее доступ к подмножеству ресурсов другой роли. Например:.

RoleA: ресурсы a, b, c, d
RoleB: ресурсы x, y, z
RoleC: ресурсы 1, 2, 3
User1: имеет RoleA, но ему необходимо получить доступ к ресурсу y
User2: имеет RoleB и RoleC, но не имеет доступа к ресурсу z

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

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

3) Разрешение состояния модели

Если этого недостаточно, некоторые действия могут выполняться только тогда, когда модель находится в определенном состоянии (каждая модель знает, когда что-то можно сделать). Например: заказ может быть отредактирован только в том случае, если пользователь имеет доступ к ресурсу редактирования (через шаги №1 или №2), а объект Order можно редактировать.

Пример Anoter: пользователь может получить доступ к Customer, если у него есть доступ к ресурсу /customer/view, и он владеет этим клиентом (он является контактной информацией для этого клиента).

4) Отображение информации в пользовательском интерфейсе

Роль, группа ролей или отдельные пользователи могут видеть более или менее информацию о модели, в зависимости от ее состояния.

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

Есть ли какой-либо шаблон, который мне не хватает, чтобы объединить все это авторизацию в одном месте?

Ответ 1

После долгого времени я наконец нашел ответ, который удовлетворяет всем моим требованиям: http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/.

Его решение состоит в том, чтобы рассматривать все как действие, разрешение на выполнение/вызов/независимо от того, какая роль принадлежит роли, и пользователи могут иметь несколько ролей.

То, что сияет в этом подходе, заключается в том, что проверка разрешений выполняется только для самой активности, а не для ролей.

Ответ 2

Я реализовал контроль доступа с помощью шаблона , который я нахожу непосредственно подходящим для этого. Центральный метод isSatisfiedBy. X разрешено делать y, если оно выполняется z. Например, пользователю разрешено просматривать "страницу администратора", если он удовлетворен "имеет роль администратора". Посмотрите, как isSatisfiedBy может быть очень общим (например, "пользователь с id 324", "был зарегистрирован в течение 30 минут", "является членом группы foo",...). Затем правила становятся следующей общей формы:

allow X to do Y if X satisfies Z