面试知识库
进阶

RBAC权限模型设计#

一句话答案#

RBAC(基于角色的访问控制)核心是「用户 → 角色 → 权限」三层映射,通过角色聚合权限简化管理;扩展模型包括角色继承(RBAC1)、互斥角色(RBAC2)、以及 ABAC 属性级细粒度控制。

核心要点

RBAC 核心模型#

用户 (User)  ←M:N→  角色 (Role)  ←M:N→  权限 (Permission)

表设计:
┌──────────┐    ┌──────────────┐    ┌──────────┐    ┌──────────────┐    ┌────────────┐
│   user   │    │  user_role   │    │   role   │    │role_permission│    │ permission │
├──────────┤    ├──────────────┤    ├──────────┤    ├──────────────┤    ├────────────┤
│ id       │    │ user_id (FK) │    │ id       │    │ role_id (FK) │    │ id         │
│ username │    │ role_id (FK) │    │ name     │    │ perm_id (FK) │    │ resource   │
│ ...      │    └──────────────┘    │ desc     │    └──────────────┘    │ action     │
└──────────┘                        └──────────┘                        │ desc       │
                                                                        └────────────┘
plaintext

权限粒度设计#

权限 = 资源 + 操作
例:
  order:read      — 查看订单
  order:create    — 创建订单
  order:delete    — 删除订单
  user:manage     — 管理用户
  report:export   — 导出报表

层级控制:
  菜单权限:控制能看到哪些菜单
  按钮权限:控制能点击哪些操作
  数据权限:控制能看到哪些数据行(如只能看自己部门的)
plaintext

RBAC 扩展模型#

模型特性场景
RBAC0基础用户-角色-权限简单系统
RBAC1角色继承(管理员 > 编辑 > 访客)层级组织
RBAC2互斥角色 + 基数约束合规要求(出纳≠审计)
RBAC3RBAC1 + RBAC2复杂企业系统

数据权限#

问题:RBAC 控制"能不能做某操作",但不控制"能看到哪些数据"

方案1: 行级过滤(推荐)
  SELECT * FROM orders WHERE dept_id IN (用户可见部门列表)
  → MyBatis 拦截器自动拼接条件

方案2: 数据标签
  每条数据打标签(部门/区域),查询时按标签过滤

方案3: 规则引擎
  定义规则:"华东区经理可见华东+华中数据"
  → 动态生成过滤条件
plaintext

权限缓存设计#

用户登录时:
1. 查库获取: 用户 → 角色列表 → 权限列表
2. 缓存到 Redis: user:{id}:permissions → Set<String>
3. 每次请求从 Redis 读取权限集合做校验
4. 角色/权限变更时: 清除相关用户缓存

缓存结构:
  key: user:123:perms
  value: {"order:read", "order:create", "user:view"}
  TTL: 30min(定期刷新)
plaintext

Spring Security 集成#

// 方法级别
@PreAuthorize("hasAuthority('order:delete')")
public void deleteOrder(Long id) { ... }

// 动态权限(从 DB 加载 URL-权限映射)
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {
    http.authorizeHttpRequests(auth -> auth
        .anyRequest().access(dynamicAuthorizationManager));
}
java
面试回答(2分钟版)

RBAC 的核心思想是在用户和权限之间加一层角色:用户关联角色,角色关联权限,这样管理 1000 个用户只需管理几个角色的权限分配。表设计是五张表:user、role、permission 三张主表加两张关联表 user_role 和 role_permission。权限定义为”资源:操作”格式,如 order:read、order:delete。扩展模型包括角色继承(RBAC1,管理员自动拥有普通用户权限)和互斥角色(RBAC2,一个人不能同时是出纳和审计)。数据权限是 RBAC 的补充——控制的不是”能不能做”而是”能看到哪些数据”,通常用 MyBatis 拦截器自动给 SQL 拼接部门/区域过滤条件。性能上,用户权限集合缓存到 Redis,登录时加载,角色变更时清缓存。Spring Security 集成用 @PreAuthorize 注解做方法级鉴权。

追问与易错

追问方向:

  • “RBAC 和 ABAC 区别?”→ RBAC 基于角色静态授权;ABAC 基于属性(时间/地点/部门)动态决策
  • “数据权限怎么实现?”→ MyBatis 拦截器 + 数据范围注解,自动拼接 WHERE 条件
  • “权限变更怎么实时生效?”→ 变更时清 Redis 缓存 + 下次请求重新加载
  • “超级管理员怎么设计?”→ 特殊标记跳过权限校验,或赋予所有权限的特殊角色

易错点:

  • ❌ “RBAC 能解决所有权限问题”——数据权限需要额外方案,动态条件需要 ABAC
  • ❌ “角色就是权限”——角色是权限的集合,一个角色对应多个权限
  • ❌ “权限只需要控制 API”——还需要前端菜单/按钮权限 + 后端数据权限