我们假设我有一个项目表:
CREATE TABLE items
(
item serial PRIMARY KEY,
...
);
现在我想介绍"权限"的概念。对于每个项目(请注意,我不在这里讨论数据库访问权限,但该项目的业务逻辑权限)。每个项目都具有默认权限以及可能覆盖默认权限的每用户权限。
我试着想办法实现这个,并想出了以下解决方案:
为每个权限使用布尔列:
CREATE TABLE items
(
item serial PRIMARY KEY,
can_change_description boolean NOT NULL,
can_change_price boolean NOT NULL,
can_delete_item_from_store boolean NOT NULL,
...
);
CREATE TABLE item_per_user_permissions
(
item int NOT NULL REFERENCES items(item),
user int NOT NULL REFERENCES users(user),
PRIMARY KEY(item, user),
can_change_description boolean NOT NULL,
can_change_price boolean NOT NULL,
can_delete_item_from_store boolean NOT NULL,
...
);
优点:每个权限都被命名。
缺点:有许多权限会显着增加列数,您必须定义两次(每个表一次)。
使用整数并将其视为位域(即位0用于can_change_description
,位1用于can_change_price
,依此类推,并使用按位运算来设置或读取权限。 / p>
CREATE DOMAIN permissions AS integer;
优势:非常快。
缺点:您必须跟踪哪个位代表数据库和前端界面中的哪个权限。
与2相同,但使用bit(n)
。最有可能是相同的优点和缺点,可能会稍微慢一些。
使用枚举类型获取权限:
CREATE TYPE permission AS ENUM ('can_change_description', 'can_change_price', .....);
然后为默认权限创建一个额外的表:
CREATE TABLE item_default_permissions
(
item int NOT NULL REFERENCES items(item),
perm permission NOT NULL,
PRIMARY KEY(item, perm)
);
并将每用户定义表更改为:
CREATE TABLE item_per_user_permissions
(
item int NOT NULL REFERENCES items(item),
user int NOT NULL REFERENCES users(user),
perm permission NOT NULL,
PRIMARY KEY(item, user, perm)
);
优势:轻松命名个人权限(您不必处理位位置)。
缺点:即使只是检索默认权限,它也需要访问另外两个表:第一个是默认权限表,第二个是存储枚举值的系统目录。
特别是因为必须为该项目的每个页面视图检索默认权限,所以最后一个替代方案的性能影响可能很大。
你能想到其他选择吗?
应该采取哪种方法?
请注意:此问题为reposted on DBA。
答案 0 :(得分:1)
这实际上取决于您需要获得权限的级别
基于角色 - 非用户
基于用户 - (更难维护)
或两者的组合
用户和角色......
以下是我们的系统 用户表 - >包含UserNames等
角色=> Office支持,机械师等角色列表
安全级别 - >等级列表,例如只读,管理员
应用功能表 - >包含可以应用权限的函数,例如Can_Edit_Users
应用程序安全性表 - >用户名+应用程序功能ID,角色和任意位/是否为权限 - 或使用安全级别的更复杂角色级别的整数。
这提供了最大的灵活性,但是很难为其构建UI。
在应用程序中,我们获取用户权限一次,并执行一项功能来检查他们是否具有权限
e.g。 CurrentUser.HasPermissions(" Can_Edit_Users&#34)
public bool HasPermissions(string Permission)
{
return this.Permissions.Any(p=>p.FunctionName==Permission && IsAllowed==true);
}