RBAC模型
常见的权限控制模型主要有三种:
-
粗粒度控制(硬编码)
比如直接在接口里写 if 判断某个用户 ID 或角色字符串,这种方式简单但不易维护,扩展性差。
-
ACL(Access Control List)访问控制列表
给每个用户分配具体权限,权限控制到“用户-资源”级别,灵活但不易管理,尤其是用户多、权限复杂时维护成本非常高。
-
RBAC(Role-Based Access Control)角色权限控制
用户 → 拥有角色,角色 → 拥有权限,权限再映射到资源或操作。抽象出“角色”作为中间层,复用性更高,也便于后台配置和系统扩展。
为什么选择 RBAC?
我这个项目有普通用户、VIP 用户、管理员三类身份,不同角色对应不同权限。为了做到权限清晰、可配置、易维护,我选择了 RBAC。
RBAC 的优势在于:
- 权限配置集中、统一,不会分散在代码中;
- 不同角色对应不同操作权限,修改角色就能控制一批权限;
- 后台可以实现可视化的权限管理,甚至后期接入前端菜单动态生成都更方便。
我的 RBAC 实现方式(3张主表 + 2张关联表)
在数据库中我设计了五张表:
user用户表role角色表permission权限表user_role用户-角色关联表role_permission角色-权限关联表
每个用户可以有多个角色,每个角色对应多个权限,这样结构上可以灵活扩展。
在权限校验上,我是通过 注解 + 拦截器 的方式实现的,整体逻辑如下:
每当用户访问接口时,我的拦截器会在方法执行前先做一层权限判断。
✅ 第一步:获取注解内容
拦截器通过反射拿到当前方法上的注解,比如:
@PreAuthorize("system:user:edit")@PreAuthorizeRole("ADMIN")
我会先判断这个接口要求的具体权限点或角色身份是什么。
✅ 第二步:获取用户登录态
然后我会从 Redis 中根据 Token 拿到当前登录用户的信息。这个信息在用户登录时就已经缓存了,包括:
- 用户 ID
- 拥有的角色列表(比如:["USER", "VIP"])
✅ 第三步:角色 → 权限展开
接下来,我会从 Redis 中根据这些角色,查出该用户所有的权限集合。
- 这里权限和角色是多对多关系,用户拥有多个角色,每个角色对应多个权限;
- 所以我会做一次权限合并 + 去重操作,拿到这个用户最终的权限全集;
- 最后判断注解里要求的权限是否在这个集合中。
这套逻辑相比在代码里写 if 判断角色或者 userId 更加清晰统一,权限声明与业务逻辑解耦,而且我在注解拦截逻辑里还预留了日志记录点,后续可以统计权限命中率或者审计操作日志。
💬 评论