RBAC
做后台系统时,权限设计通常都会碰到一个问题:权限到底应该直接分给用户,还是先抽象出一层角色,再由角色去承载权限?大多数中后台项目最后都会走到同一个答案上:RBAC。
RBAC 是 Role-Based Access Control 的缩写,中文通常译为“基于角色的访问控制”。它做的事情并不复杂:权限不直接分配给用户,而是先分配给角色,再由用户拥有一个或多个角色,从而间接获得对应权限。这套模型并不新,但直到今天,它依然是很多业务系统授权设计的基础,因为它比较稳定,也比较容易维护。
为什么需要 RBAC
如果系统里只有三五个用户,直接给每个人单独配置权限,看起来也不是不行。但只要用户规模上来,问题就会很快出现:
- 新增一个岗位,要给很多人重复配置同样的权限。
- 某个权限变更,要逐个检查谁受影响。
- 人员离职或调岗后,旧权限很容易残留。
权限系统一旦和“具体的人”强绑定,后面通常会越来越难维护。RBAC 的思路比较直接,就是把“人”和“权限”拆开,在中间加一层角色。
比如,一个系统里可以有“普通用户”“管理员”“教师”“审计员”这些角色。用户不直接拥有“删除文章”“审核订单”“导出报表”这些权限,而是先拥有某个角色,再由角色去绑定权限。
也就是说,权限不再直接跟某个具体用户绑定,而是先跟角色绑定。
- 权限管理更稳定。人员会变化,但职责通常比人员稳定得多。
- 权限调整更集中。改角色的权限,往往就等于批量调整一组用户的能力。
RBAC 的基本模型
从关系上看,RBAC 主要处理三件事:
- 用户属于哪些角色
- 角色拥有哪些权限
- 系统访问资源时,如何根据角色完成授权判断
可以用一张图来理解这个关系:
flowchart LR
U[用户 User] --> R[角色 Role]
R --> P1[权限 Permission: 读取]
R --> P2[权限 Permission: 编辑]
R --> P3[权限 Permission: 删除]
P1 --> RES[资源 Resource]
P2 --> RES
P3 --> RES
这张图最关键的地方,不是“用户最后拥有哪些权限”,而是“用户是通过角色拿到权限的”。也正是因为多了这一层,RBAC 才能在业务系统里长期使用。
RBAC 的核心特性
RBAC 不只是“给用户挂几个角色”这么简单。一个比较完整的 RBAC 设计,通常还会包括下面这些内容。
角色层级
角色之间可以存在继承关系。例如管理员通常天然拥有普通用户的权限。这样可以减少重复配置,也更接近真实业务里的职责结构。
最小权限
用户只拿完成当前职责所必需的权限,不额外授予更高的访问能力。这个原则本身不只属于 RBAC,但 RBAC 很适合把“最小权限”落实到角色设计里。
职责分离
一些高风险操作不应该由同一种角色独立完成。例如“提交申请”和“审批申请”可以拆给不同角色,避免权限过于集中。
这也是为什么很多系统里的“操作员”和“审核员”会被刻意拆开。这样做不一定让系统更简单,但通常会更安全。
在 Spring Security 中如何落地 RBAC
在 Spring Security 里,RBAC 最常见的落地方式,是把角色映射为 GrantedAuthority。框架本身并不强制只能使用角色,但在大多数后台系统里,角色依然是最好维护的一层抽象。
例如,数据库中如果存的是 USER 和 ADMIN,通常会在加载用户时映射成 ROLE_USER 和 ROLE_ADMIN:
1 | List<GrantedAuthority> authorities = new ArrayList<>(); |
这里有一个很常见的约定:hasRole("ADMIN") 最终匹配的是 ROLE_ADMIN。也就是说,Spring Security 在处理角色时通常默认带有 ROLE_ 前缀。
这个映射动作,本质上就是把业务里的角色定义转换成安全框架能识别的授权信息。
落到项目里,RBAC 一般会出现在两个层面。
URL 级别控制
这类规则适合放在接口路径这一层,先做第一道限制:
1 | http.authorizeHttpRequests(auth -> auth |
方法级别控制
如果要控制得更细,一般就会落到方法级别:
1 |
|
这两种方式可以一起使用。路径规则负责第一层拦截,方法注解负责更贴近业务语义的二次校验。前者更偏资源入口控制,后者更偏业务动作控制。
如果系统还用了 JWT,那么令牌里通常也会带上角色信息。服务端解析完令牌之后,再把角色转换为 GrantedAuthority,后面的授权判断就还是走 Spring Security 这一套。
什么时候单靠 RBAC 不够
RBAC 很适合职责稳定、岗位清晰的系统,但它并不是万能方案。
如果权限判断强依赖上下文,比如:
- 只能查看自己创建的数据
- 只能审批本部门的数据
- 某个角色只能在指定租户下操作
- 某项操作只有在工作时间内才允许执行
这时候,单纯按角色判断基本就不够了。通常还需要在 RBAC 之外,再叠加资源归属、部门范围、租户信息,或者更细粒度的策略判断。
所以更准确的说法是,RBAC 更适合做授权体系的基础层,而不是把所有权限问题都只交给它来解决。很多系统最后也不是“只用 RBAC”,而是先用 RBAC 把大框架搭起来,再补数据级和场景级规则。
小结
RBAC 的价值,不在于概念有多新,而在于它能把原本很容易失控的用户权限关系,整理成一个可维护、可演进的角色模型。
对于 Spring Security 项目来说,只要把角色清晰地映射到 GrantedAuthority,再配合 URL 级别和方法级别的访问控制,通常就已经能覆盖大部分后台系统的授权需求。
如果你正在做一个中后台项目,又不想让权限系统从一开始就变得混乱,那么从 RBAC 起步,通常是一个比较稳妥的选择。
参考资料
- NIST RBAC FAQ: https://csrc.nist.gov/projects/role-based-access-control/faqs
- Spring Security Reference, Authorization Architecture: https://docs.spring.io/spring-security/reference/servlet/authorization/architecture.html
- OWASP Authorization Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html