2、权限矩阵模型:RBAC模型介绍、权限矩阵的存储结构(用户-角色-权限)、JWT中嵌入权限信息的常见方式

2.1 RBAC 模型:从用户到权限的标准化映射

基于角色的访问控制(RBAC)是业界最成熟的权限管理模型之一。其核心思想是将“权限”与“角色”绑定,再将“角色”授予“用户”,从而在用户与权限之间建立一层间接抽象。这种设计大幅降低了权限管理的复杂度,尤其适合企业级后端系统。

RBAC 模型包含三个基本实体:

  • 用户(User):系统的操作主体,可以是一个人、一个服务账号或一个设备。
  • 角色(Role):权限的集合,代表一类职责或岗位,例如“管理员”、“编辑”、“审计员”。
  • 权限(Permission):对某个资源执行特定操作的许可,通常表示为 resource:action 格式,例如 order:create、report:export。
RBAC 核心优势:当组织内新增用户时,只需为其分配已有角色,无需逐条配置权限;当业务权限变更时,只需修改角色与权限的关联,所有拥有该角色的用户自动生效。

2.2 权限矩阵的存储结构:用户-角色-权限三层关联

在关系型数据库中,RBAC 通常通过三张核心表及两张关联表实现。以下为标准的五表结构设计:

表名 字段示例 说明
users id, username, password_hash 用户主体表
roles id, role_name, description 角色定义表
permissions id, resource, action 权限原子表
user_roles user_id, role_id 用户与角色的多对多关联
role_permissions role_id, permission_id 角色与权限的多对多关联

查询某个用户的所有权限时,执行以下 SQL 关联:

SELECT p.resource, p.action
FROM users u
JOIN user_roles ur ON u.id = ur.user_id
JOIN roles r ON ur.role_id = r.id
JOIN role_permissions rp ON r.id = rp.role_id
JOIN permissions p ON rp.permission_id = p.id
WHERE u.id = ?;

这种存储结构在数据层面保证了权限的完整性和一致性,但在高并发场景下,每次请求都执行多表 JOIN 查询会带来显著的性能开销。这正是后续章节引入缓存策略的直接动因。

设计建议:权限的 resource 和 action 字段建议使用枚举或短字符串,并建立联合索引,以加速权限查询。

2.3 JWT 中嵌入权限信息的常见方式

将权限信息嵌入 JWT 令牌,可以使后端服务在无状态鉴权时直接获取用户的权限矩阵,避免每次请求都回查数据库。根据业务规模和性能要求,主要有以下三种嵌入策略:

方式一:直接嵌入角色列表(轻量级)

在 JWT 的 payload 中仅存放用户所属的角色名称列表。后端收到请求后,从令牌中提取角色,再通过本地缓存或内存中的角色-权限映射表完成鉴权。

{
  "sub": "user_1001",
  "roles": ["admin", "editor"],
  "iat": 1710000000,
  "exp": 1710003600
}

适用场景:角色数量少(通常 < 20 个),且角色与权限的映射关系相对稳定。

方式二:嵌入权限标识列表(精细粒度)

直接将用户拥有的所有权限标识(如 order:create、report:export)放入 JWT。后端无需二次查询即可完成精确鉴权。

{
  "sub": "user_1001",
  "permissions": [
    "order:create",
    "order:view",
    "report:export",
    "user:manage"
  ],
  "iat": 1710000000,
  "exp": 1710003600
}

适用场景:权限粒度要求精细,且单个用户的权限数量可控(通常 < 200 条)。

性能警告:当用户权限数量超过 500 条时,JWT 的 payload 体积会显著增大,导致每次请求的 HTTP 头部传输开销上升,同时增加令牌签发和验签的耗时。此时应考虑方式三或引入压缩策略。

方式三:嵌入权限位图(极致性能)

将权限系统预定义为一个有序的权限列表,每个权限对应一个二进制位。用户的权限集合通过一个位图(Bitmap)表示,JWT 中仅存储该位图的整数值或 Base64 编码字符串。

// 权限定义索引
// 0: order:create
// 1: order:view
// 2: order:delete
// 3: report:export
// 4: user:manage

// 用户拥有 order:create, order:view, report:export
// 位图: 1 1 0 1 0 → 二进制 11010 → 十进制 26

{
  "sub": "user_1001",
  "perm_bitmap": 26,
  "iat": 1710000000,
  "exp": 1710003600
}

适用场景:权限总数固定且较少(通常 < 64 个),对令牌体积和解析速度有极致要求的场景。

2.4 三种嵌入方式对比

对比维度 角色列表 权限标识列表 权限位图
令牌体积 小 中~大 极小
鉴权速度 中(需查角色-权限映射) 快(直接匹配) 极快(位运算)
扩展性 高(角色增删不影响令牌) 低(权限变更需重新签发令牌) 中(权限列表重排需同步更新)
实现复杂度 低 中 高
推荐场景 角色少、权限层级简单 权限粒度细、数量适中 高并发、权限总数固定

2.5 权限矩阵与 JWT 嵌入的整体架构

下图展示了从数据库存储到 JWT 签发,再到请求鉴权的完整数据流:

权限矩阵存储与 JWT 嵌入架构 关系型数据库 users 表 roles 表 permissions 表 user_roles / role_permissions 权限服务 查询用户权限 组装权限集合 选择嵌入策略 生成 JWT payload JWT 令牌 Header Payload(含权限) Signature 签发并返回客户端 SQL 查询 嵌入权限 请求鉴权流程(无状态) 客户端请求 携带 JWT API 网关/中间件 验签 + 解析 payload 权限校验器 提取权限信息 业务服务 放行/拒绝 整个鉴权过程不查询数据库,完全依赖 JWT 中的权限信息