如何在PostgreSQL中实现业务逻辑权限?

Joh*_*and 5 sql postgresql permissions

我们假设我有一个项目表:

CREATE TABLE items
(
    item serial PRIMARY KEY,
    ...
);
Run Code Online (Sandbox Code Playgroud)

现在我想为每个项目引入"权限"的概念(注意,我不是在谈论数据库访问权限,而是在谈论该项目的业务逻辑权限).每个项目都具有默认权限以及可能覆盖默认权限的每用户权限.

我试着想办法实现这个,并想出了以下解决方案:

1)布尔解决方案

对每个权限使用布尔列:

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,
    ...
);
Run Code Online (Sandbox Code Playgroud)

优点:每个权限都被命名.

缺点:有许多权限会显着增加列数,您必须定义两次(每个表一次).

2)整数解决方案

使用整数并将其视为位域(即位0用于can_change_description,位1用于can_change_price,依此类推,并使用按位运算来设置或读取权限).

CREATE DOMAIN permissions AS integer;
Run Code Online (Sandbox Code Playgroud)

优点:非常快.

缺点:您必须跟踪哪个位代表数据库和前端接口中的哪个权限.

3)比特场解决方案

与2)相同,但使用bit(n).最有可能是相同的优点和缺点,也许稍微慢一点.

4)Enum解决方案

使用枚举类型进行权限:

CREATE TYPE permission AS ENUM ('can_change_description', 'can_change_price', .....);
Run Code Online (Sandbox Code Playgroud)

然后为默认权限创建一个额外的表:

CREATE TABLE item_default_permissions
(
    item int NOT NULL REFERENCES items(item),
    perm permission NOT NULL,

    PRIMARY KEY(item, perm)
);
Run Code Online (Sandbox Code Playgroud)

并将每用户定义表更改为:

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)    
);
Run Code Online (Sandbox Code Playgroud)

优点:易于命名个人权限(您不必处理位位置).

缺点:即使只是检索默认权限,它也需要访问另外两个表:第一个是默认权限表,第二个是存储枚举值的系统目录.

特别是因为必须为该项目的每个页面视图检索默认权限,所以最后一个替代方案的性能影响可能很大.

你能想到其他选择吗?

应该采取哪种方法?

请注意:此问题已转发给DBA.

Tra*_*aci 1

这实际上取决于您需要达到什么级别才能获得权限

基于角色 - 非用户

基于用户-(更难维护)

或两者的组合

用户和角色...

我们系统上的以下用户表 -> 包含用户名等

角色 => 角色列表,例如办公室支持、机械师

安全级别 -> 级别列表,例如只读、管理员

应用程序函数表 -> 包含可以应用权限的函数,例如 Can_Edit_Users

应用程序安全表 -> 用户名 + 应用程序功能 ID、角色以及表示是/否权限的任一位 - 或使用安全级别的更复杂角色级别的整数。

这提供了最大的灵活性,但构建 UI 可能很困难。

在应用程序中,我们获取用户权限一次,并执行一个函数来检查他们是否具有权限

例如 CurrentUser.HasPermissions("Can_Edit_Users")

public bool HasPermissions(string Permission)
{
return this.Permissions.Any(p=>p.FunctionName==Permission && IsAllowed==true);
}
Run Code Online (Sandbox Code Playgroud)