Я недавно подошел к этой проблеме и в итоге использовал решение, которое приблизительно управление доступом на основе ролей
В общих чертах система, которую я реализовал, была описана как
- Темы: реальных пользователей с возможностью аутентификации , например, с помощью пароля
- Разрешения: для представления любого контролируемого ресурса; Если у пользователя есть разрешение, он уполномочен использовать этот ресурс;
- Роли: Связи между субъектами и разрешениями; каждой роли назначается определенный набор субъектов, разрешений и других ролей;
Важным моментом, который необходимо понять, является назначение роли; соединение от одной роли к другой является не рефлексивным; Субъекты в родительской роли имеют доступ к разрешениям в дочерней роли, но не наоборот, субъекты не авторизованы на разрешения через родителей ролей, которым назначены эти субъекты. Дополнительным ограничением является то, что роли не разрешено наследовать от себя; хотя на самом деле это только для того, чтобы облегчить понимание результирующего графика ролей и избежать случайного предоставления разрешений большим группам субъектов.
При правильной комбинации разрешений это оказывается очень выразительным; Вы можете иметь роли для предоставления общего доступа, а также для авторизации более конкретных глаголов или объектов; а затем ваше приложение проверяет, чтобы убедиться, что субъект имеет все необходимые разрешения (может получить доступ, может выполнить это действие, может изменить этот объект)
Структура, в которой роли заканчиваются, является частичным порядком; и простой список смежных ролей оказывается неудобным способом запроса разрешений субъекта (на MySQL, где он будет работать), поэтому мне также пришлось разработать набор триггеров, чтобы поддерживать второе отношение в актуальном состоянии до выразить транзитивное закрытие ролевых назначений.
Обновление:
Кажется, рекурсивная структура ролей добавила больше сложностей, чем решала, по крайней мере для этого конкретного приложения, поскольку роли в значительной степени управляются службой поддержки, а не самим дизайном приложения. То, как я это реализовал в настоящее время, пользователи могут быть в группах, и каждой группе назначен набор разрешений. Каждое «назначение» имеет приоритет и может либо предоставлять, либо отклонять соответствующее разрешение. разрешение с наивысшим приоритетом выигрывает. схема примерно:
CREATE TABLE user (
username VARCHAR PRIMARY KEY,
hashedpassword VARCHAR);
CREATE TABLE groups (
groupname VARCHAR PRIMARY KEY );
CREATE TABLE user_groups (
username VARCHAR PRIMARY KEY REFERENCES user(username),
groupname VARCHAR PRIMARY KEY REFERENCES groups(groupname),
CREATE TABLE permission (
permissionname VARCHAR PRIMARY KEY,
defaultpolicy BOOLEAN );
CREATE TABLE group_permission (
permissionname VARCHAR PRIMARY KEY REFERENCES permission(permissionname),
groupname VARCHAR PRIMARY KEY REFERENCES groups(groupname),
priority INTEGER,
policy BOOLEAN );
Нерекурсивная структура значительно упрощает разрешение разрешения;
(
SELECT policy, priority
FROM group_permission
JOIN user_groups ON user_groups.groupname = group_permissions.groupname
WHERE username = :username
AND permissionname = :perm
UNION
SELECT
defaultpolicy as policy,
(SELECT min(priority) - 1 FROM group_permission) as priority
FROM permission
WHERE permissionname = :perm
)
ORDER BY priority DESC
LIMIT 1