Вот мой подход к таким системам RBAC, сначала я бы разделить приложение на модули, по крайней мере, логически.
Подумайте о модулях как сущностях/ресурсах в вашем приложении, на которых могут выполняться определенные действия. Ресурс может быть ПОЛЬЗОВАТЕЛЬ, членство, продукт, ..
Давайте предположим, что мы строим сайт как Stackoverflow и мы имеем следующие модули:
Каждый из этих модулей регистрируются в таблице базы данных приложений под названием modules
, которые могли бы выглядеть следующим образом:
# Modules
- id [an application-wide unique module identifier, provided by the module]
- name [string, human readable]
Каждый из этих модулей имеет набор действий, которые предварительно определены модулем, например, действия по созданию вопроса, запуск пользователей из чатов и т. Д. Эти действия устанавливаются вместе с модулями в базу данных приложений стол под названием «действия», которые могли бы выглядеть следующим образом:
# Actions
- module_id [reference to the modules table, is the namespace for the token]
- action [string/int, action identifier provided by the module, unique in the scope of the module]
- name [string, human readable name]
- Primary Key: [module_id, action]
Давайте определим модули и действия для нашего клона StackOverflow Сейчас:
Modules
+------------------------------------------+
| ID | Name |
+------------------------------------------+
| questions | Question and Answer Module |
| chat | Chat Module |
+------------------------------------------+
Наряду с модулями, будут установлены действия:
Actions
+-----------------------------------------------+
| Module | Action | Name |
+-----------------------------------------------+
| questions | read | Read Questions |
| questions | create | Create Questions |
| questions | edit | Edit Questions |
| questions | delete | Delete Questions |
| questions | vote | Vote on Questions |
| | | |
| chat | join | Join the Chat |
| chat | kick | Kick users |
| chat | create | Create Chatrooms |
+-----------------------------------------------+
Важным здесь является то, что вы не можете изменить данные в этих таблицах непосредственно в качестве администратора систем, так что нет GUI , чтобы добавить/удалить действия и т.д.
Следующий шаг - создать некоторые роли для нашей системы, это делается через пользовательский интерфейс администратора, роли могут быть определены произвольно.
Давайте начнем с некоторых основных ролях:
Q&A User:
- can read questions
- can create questions
Q&A Moderator:
- can read questions
- can create questions
- can vote on questiosn
- can edit questions
Q&A Admin:
- can read questions
- can create questions
- can vote on questiosn
- can edit questions
- can delete questions
Chat User:
- can join the chat
Chat Moderator:
- can join the chat
- can kick users from the chat
Chat Admin:
- can join the chat
- can kick users from the chat
- can create chat rooms
Во-первых, роли создаются в таблице ролей:
# Roles
- id [auto-increment, unsigned]
- name [string, length:50]
Населенные с нашими пользовательских определений:
Roles
+-----------------------+
| ID | Name |
+-----------------------+
| 1 | Q&A User |
| 2 | Q&A Moderator |
| 3 | Q&A Admin |
| 4 | Chat User |
| 5 | Chat Moderator |
| 6 | Chat Admin |
+-----------------------+
В нашем супермощном пользовательском интерфейсе администратора теперь есть боковая панель со списком всех установленных модулей и их ассоциатов действия. Начиная с наш типичный администратор супер ленив и ничего не знает о программировании, он теперь может удобно назначать действия для каждой роли с помощью drag & drop, т. Е. Назначая разрешения для ролей.
Этих назначенных разрешений хранится в нашей таблице отображения Roles_Actions
:
# Roles_Actions
- role_id
- module_id
- action
PK: [role_id, module_id, action]
заселенный стол:
Roles_Actions
+--------------------------------+
| Role ID | Module ID | Action |
+--------------------------------+
| 1 | questions | read |
| 1 | questions | create |
| 2 | questions | read |
| 2 | questions | create |
| 2 | questions | vote |
| 2 | questions | edit |
...
| 6 | chat | join |
| 6 | chat | kick |
| 6 | chat | create |
+--------------------------------+
Теперь мы должны назначить роли для пользователей в системах, скажем мы имеют первоначально четырех пользователей:
- Chuck Norris which is a Q&A Admin and also a Chat Admin (UID = 1)
- Bruce Willis which is a Q&A Moderator and a Chat User (UID = 2)
- Dilbert which is a Q&A Moderator and a Chat Moderator (UID = 3)
# User_Roles
- user_id [FK:user_id, unsigned]
- role_id [FK:roles_id, unsigned]
Заселенный стол:
Users_Roles
+---------------------------------+
| User ID | Role ID |
+---------------------------------+
| 1 | 3 (= Q&A Admin) |
| 1 | 6 (= Chat Admin) |
| 2 | 2 (= Q&A Moderator) |
| 2 | 4 (= Chat User) |
| 3 | 2 (= Q&A Moderator) |
| 3 | 5 (= Chat Moderator) |
+---------------------------------+
Так один пользователь может иметь несколько ролей и разрешений (пар модуль/действие), затем объединены вместе в уровне приложений. Если вы хотите перейти на один шаг дальше, вы также можете предоставить какое-то наследование в ролевой модели, например Q & Модератор может быть определен как дочерний элемент Q & Пользователь, наследующий все разрешения от Q & A Пользователь и распространяя его на права модератора.
Так как же может возникнуть авторизация на уровне приложения?
Предположим, что Dilbert, который является Q & Модератор Модератор и Чат, регистрируется в системе, затем вы собираете все его роли и все права, назначенные этим ролям.Затем вы начинаете строить дерево разрешения и удалить все дубликаты разрешений, дерево разрешение может быть представлена в виде ассоциативного массива, как:
Дилберта разрешение дерева:
$dilberts_permissions = array(
"questions" => array("read", "create", "vote", "edit")
"chat" => array("join", "kick")
)
Для удобства мы создаем простую вспомогательную функцию как:
function has_permission($path, $tree) {
list($module, $action) = explode('.', $path);
return (array_key_exists($module, $tree) && in_array($action, $tree[$module]));
}
в нашем коде теперь мы можем проверить, если Дилберта разрешено делать определенные вещи с синтаксисом, как:
has_permission("questions.create", $dilberts_permissions); // => TRUE
has_permission("questions.delete", $dilberts_permissions); // => FALSE
has_permission("chat.join", $dilberts_permissions); // => TRUE
has_permission("chat.create", $dilberts_permissions); // => FALSE
вы всегда можете добавить дополнительные поля в таблицу 'role', чтобы хранить объяснения того, для чего это нужно. Но, в конце концов, фактическое название роли не имеет значения. Это сводится к тому, что соответствующая «требует ли пользователь роли» проверяет, становится ли это разрешение. Является ли это разрешение «42» или «is_superuser», не имеет большого значения. –
Я рекомендую прочитать эту статью: http://www.yiiframework.com/doc/guide/1.1/en/topics.auth#role-based-access-control и попробуйте использовать для этого некоторую фреймворкную структуру, потому что все это охлаждают системы RBAC. – stepozer
@stepozer Я работаю с Laravel, у которого нет встроенной системы, но предоставляет фильтры маршрутов и промежуточное ПО, которые я буду использовать с помощью специального решения. Я хочу, чтобы не добавлять дополнительные пакеты, поскольку они слишком переполнены. Мне нужно простое решение. –