Подтвердить что ты не робот

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

Основная сделка заключается в том, что у нас есть собственный "kickstart" для наших проектов. Для этого мы пересматриваем пользовательский элемент управления. Я знаю, что есть много вопросов об общем rbac, но я не могу найти ни одного иерархического rbac?

Наши требования:

  • Роли могут быть назначены для групповых разрешений
  • Если в роли нет записи разрешения, она автоматически отказывается
  • Пользователю могут быть предоставлены переопределяющие разрешения
  • Пользователи, переопределяющие разрешения, являются либо грантом, либо deny
  • Если пользователю явно отказано в разрешении, независимо от того, какие роли говорят "предоставлено", выигрывает переопределение.
  • Пользователи могут иметь несколько ролей
  • Роли могут иметь иерархию
  • Роли могут наследоваться от других ролей (например, роль "Модератор форума" "Модератор форума" - это "Модератор форума" и "Системный помощник", а роль "Модератор форума" уже наследуется от роли "Пользователь Форума" )/li >
  • Роли, которые наследуются от другой роли, которая отказывает или предоставляет привилегию, переопределяет их дочернее разрешение.
  • Разрешения сгруппированы по модулю (например, модуль "Блог" может иметь разрешение "редактировать запись", а модуль "Форум" может иметь разрешение "редактировать запись", и они не будут сталкиваться)
  • Имеется разрешение "Все и все", которое автоматически предоставляет полный доступ

Итак, с учетом этих требований, вот как я думаю об этом.

Таблица: пользователи

id            | int     | unique id

Таблица: Роли

id            | int     | unique id
--------------|---------------------------------------------
title         | varchar | human readable name

Таблица: Разрешения

id            | int     | unique id
--------------|---------------------------------------------
module        | varchar | module name
--------------|---------------------------------------------
title         | varchar | human readable name
--------------|---------------------------------------------
key           | varchar | key name used in functions

Таблица: Role_User

role_id       | int     | id from roles table
--------------|---------------------------------------------
user_id       | int     | id from users table

Таблица: Permission_Role

id            | int     | unique id
--------------|---------------------------------------------
permission_id | int     | id from permissions table
--------------|---------------------------------------------
role_id       | int     | id from roles table
--------------|---------------------------------------------
grant         | tinyint | 0 = deny, 1 = grant

Таблица: Permission_User

id            | int     | unique id
--------------|---------------------------------------------
permission_id | int     | id from permissions table
--------------|---------------------------------------------
user_id       | int     | id from users table
--------------|---------------------------------------------
grant         | tinyint | 0 = deny, 1 = grant

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

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

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

Разрешения пользователя - это легкая часть, разрешения для каждого пользователя по существу являются окончательно разрешенной группой.

4b9b3361

Ответ 1

Существует способ реализовать наследование роли с помощью рекурсивного отношения к таблице Roles, сделав ссылку на другую запись:

1:n inheritance

Это отношение добавит наследование 1 : n в записи Roles. Вы можете получить целое дерево иерархии с помощью этой хранимой функции:

CREATE FUNCTION `getHierarchy`(`aRole` BIGINT UNSIGNED)
RETURNS VARCHAR(1024)
NOT DETERMINISTIC
READS SQL DATA
BEGIN
DECLARE `aResult` VARCHAR(1024) DEFAULT NULL;
DECLARE `aParent` BIGINT UNSIGNED;

SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aRole`);

WHILE NOT `aParent` IS NULL DO

    SET `aResult` = CONCAT_WS(',', `aResult`, `aParent`);
    SET `aParent` = (SELECT `parent` FROM `Roles` WHERE `id` = `aParent`);

END WHILE;

RETURN IFNULL(`aResult`, '');
END

Затем вы можете получить все предоставленные разрешения с чем-то вроде этого:

SELECT
    `permission_id`
FROM
    `Permission_Role`
WHERE
    FIND_IN_SET(`role_id`, `getHierarchy`({$role}))
    AND
    grant;

Если этого недостаточно, вы можете сделать другую таблицу для наследования:

n:m inheritance

Но в этом случае нужен еще один алгоритм получения иерархии.


Чтобы решить проблему переопределения, вам нужно будет получить разрешения на роль и разрешения пользователей. Затем напишите user разрешения на Roles разрешения на session.


Кроме того, я предлагаю удалить столбцы grant в Permission_Role и Permission_User. Нет необходимости отображать каждое разрешение для каждого из них. Достаточно просто использовать запросы EXISTS: если есть запись, то разрешение предоставляется, иначе - нет. Если вам нужно получить все разрешения и статусы, вы можете использовать LEFT JOIN s.