权限操作:RBAC+ACL搭配

1. RBAC(基于角色的访问控制)

RBAC将权限分配给角色,用户通过关联角色间接获得权限。系统通过“用户-角色-权限”的层级关系实现权限管理。

这种经典的权限控制设计有一个缺点,就是难以处理特殊个体的细粒度权限,比如我作为管理员,我需要将某个文件的访问权限交给不是管理员,但是信任的人(比如张三)进行访问。

2. ACL(访问控制列表)

ACL直接在资源上定义允许操作的主体,每条记录明确指定"谁可以对某资源做什么"

这种划分权限类似于我们平常使用的windows文件管理的方式,其主要优势在于灵活性强,每条权限规则都明确可见。但是缺点也很明显,那就是当用户数量或者资源数量很大的时候,ACL条目呈现指数级增长。

3. RBAC 与 ACL 联合使用的优势

  1. 灵活性与效率的平衡

    • RBAC 处理通用权限(如部门角色、职级权限)
    • ACL 处理例外场景(如特殊用户需要访问特定资源)

    比如,在企业系统中,普通员工通过角色获得基础权限,但某个机密文件可通过ACL单独授权给少数高管。

  2. 减少角色爆炸

    • 通过ACL补充RBAC,避免在RBAC中因为个别的特殊权限去创建冗余角色
  3. 精细化权限管理

    • RBAC管理粗粒度权限(如”访问财务模块“),ACL控制细粒度操作(如”仅能查看报表,不能导出“)
  4. 冲突解决与优先级

    • 当RBAC和ACL权限有冲突的时候,可以设定优先级,比如ACL优先于RBAC

4. RBAC + ACL模型举例

RBAC(基于角色的访问控制)经典模型中通常包含以下5张核心表:

-- 1. 用户表(3个用户)
CREATE TABLE users (
    user_id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100)
);

INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),     -- admin
('bob', 'bob@example.com'),         -- user
('charlie', 'charlie@example.com'); -- user

-- 2. 角色表(admin 和 user)
CREATE TABLE roles (
    role_id INT PRIMARY KEY AUTO_INCREMENT,
    role_name VARCHAR(50) NOT NULL UNIQUE
);

INSERT INTO roles (role_name) VALUES
('admin'),
('user');

-- 3. 权限表(只包含读和写)
CREATE TABLE permissions (
    permission_id INT PRIMARY KEY AUTO_INCREMENT,
    permission_key VARCHAR(50) NOT NULL UNIQUE
);

INSERT INTO permissions (permission_key) VALUES
('article:read'),
('article:write');

-- 4. 用户-角色关联表
CREATE TABLE user_roles (
    user_id INT,
    role_id INT,
    PRIMARY KEY (user_id, role_id),
    FOREIGN KEY (user_id) REFERENCES users(user_id),
    FOREIGN KEY (role_id) REFERENCES roles(role_id)
);

-- 分配角色(1个admin,2个user)
INSERT INTO user_roles (user_id, role_id) VALUES
(1, 1),  -- alice 是 admin
(2, 2),  -- bob 是 user
(3, 2);  -- charlie 是 user

-- 5. 角色-权限关联表
CREATE TABLE role_permissions (
    role_id INT,
    permission_id INT,
    PRIMARY KEY (role_id, permission_id),
    FOREIGN KEY (role_id) REFERENCES roles(role_id),
    FOREIGN KEY (permission_id) REFERENCES permissions(permission_id)
);

-- 权限分配:admin有读写,user只有读
INSERT INTO role_permissions (role_id, permission_id) VALUES
(1, 1),  -- admin -> article:read
(1, 2),  -- admin -> article:write
(2, 1);  -- user -> article:read

然后如果需要对权限进行更加细粒度的控制,有如下ACL表可供参考:

CREATE TABLE acl_entry (
    id INT PRIMARY KEY AUTO_INCREMENT,
    resource_type VARCHAR(50) NOT NULL,   -- 资源类型,如 article、order、comment
    resource_id INT NOT NULL,             -- 具体资源ID
    grantee_type ENUM('USER', 'ROLE') NOT NULL,  -- 授权对象类型:用户或角色
    grantee_id INT NOT NULL,              -- 被授权的用户或角色的ID
    permission VARCHAR(20) NOT NULL,      -- 权限类型,如 read、write
    created_by INT NOT NULL,              -- 授权人ID
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_acl_entry(resource_type, resource_id, grantee_type, grantee_id)
);


-- admin (user_id = 1) 给用户 (user_id = 2) 授权了对文章101的读权限
-- admin 给角色(role_id = 2,可能是 editor)授权了对文章101的写权限
INSERT INTO acl_entry (resource_type, resource_id, grantee_type, grantee_id, permission, created_by) VALUES
('article', 101, 'USER', 2, 'read', 1),
('article', 101, 'ROLE', 2, 'write', 1);
最后修改:2025 年 05 月 04 日
如果觉得我的文章对你有用,请随意赞赏