高 进阶
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 — 导出报表
层级控制:
菜单权限:控制能看到哪些菜单
按钮权限:控制能点击哪些操作
数据权限:控制能看到哪些数据行(如只能看自己部门的)plaintextRBAC 扩展模型#
| 模型 | 特性 | 场景 |
|---|---|---|
| RBAC0 | 基础用户-角色-权限 | 简单系统 |
| RBAC1 | 角色继承(管理员 > 编辑 > 访客) | 层级组织 |
| RBAC2 | 互斥角色 + 基数约束 | 合规要求(出纳≠审计) |
| RBAC3 | RBAC1 + 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(定期刷新)plaintextSpring 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”——还需要前端菜单/按钮权限 + 后端数据权限