--- title: "RBAC模型" created: 2025-11-25 --- # RBAC模型 常见的权限控制模型主要有三种: 1. **粗粒度控制(硬编码)** 比如直接在接口里写 if 判断某个用户 ID 或角色字符串,这种方式简单但不易维护,扩展性差。 2. **ACL(Access Control List)访问控制列表** 给每个用户分配具体权限,权限控制到“用户-资源”级别,灵活但不易管理,尤其是用户多、权限复杂时维护成本非常高。 3. **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 更加清晰统一,权限声明与业务逻辑解耦,而且我在注解拦截逻辑里还预留了日志记录点,后续可以统计权限命中率或者审计操作日志。