企业认证与安全体系(八):企业为什么都在用 RBAC?一篇讲透权限模型设计
2026/7/6 1:30:14 网站建设 项目流程

上一篇我们讲了:

《企业认证与安全体系(七):OAuth2 到底解决了什么问题?一篇讲透授权与第三方登录》

到这里,我们已经讲清楚了很多“认证”相关的问题:

双 Token Token + Redis JWT Spring Security Gateway OAuth2 第三方登录

这些内容主要解决的是:

你是谁? 你怎么登录? 你的登录态怎么维护? 你的请求怎么被识别?

但是,在企业系统里,仅仅知道“你是谁”还不够。

系统还必须知道:

你能访问哪些菜单? 你能点击哪些按钮? 你能调用哪些接口? 你能看到哪些数据?

这就进入了另一个非常重要的问题:

授权。

认证解决的是:

你是谁

授权解决的是:

你能干什么

而企业系统中最常见的授权模型,就是:

RBAC。

今天我们就从工程视角讲透:

企业为什么都在用 RBAC,以及权限模型到底该怎么设计。


一、先区分认证和授权

很多人刚接触安全体系时,会把认证和授权混在一起。

其实它们完全不是一回事。

认证是 Authentication。

授权是 Authorization。

简单来说:

概念解决的问题例子
认证你是谁用户登录成功,系统知道你是张三
授权你能干什么张三能不能删除订单

例如:

用户登录成功后,系统知道:

userId = 1001 username = zhangsan

这只是认证完成了。

但是用户能不能进入后台?

能不能看订单?

能不能删除订单?

能不能导出财务报表?

这些不是认证问题,而是授权问题。

所以,企业系统必须在认证之后继续做权限控制。


二、如果没有权限模型会怎样?

假设一个后台系统有这些功能:

用户管理 订单管理 商品管理 财务报表 系统配置

不同岗位的人能操作的内容肯定不一样。

例如:

用户应该拥有的权限
超级管理员所有权限
运营人员商品、订单相关权限
财务人员财务报表权限
客服人员查询订单、处理售后
普通员工只能查看部分信息

如果没有权限模型,最容易写成这样:

if (user.getUsername().equals("admin")) { // 可以删除订单 }

或者:

if (user.getType() == 1) { // 可以查看财务报表 }

一开始看起来没问题。

但是项目一复杂,问题马上出现。


三、为什么不能到处写 if(admin)

企业项目最怕的就是权限逻辑散落在各个地方。

例如:

if (isAdmin) { deleteOrder(); }
if (userType == 2) { exportReport(); }
if (roleName.equals("manager")) { updateUser(); }

这种写法有几个明显问题。

1. 权限逻辑分散

权限判断散落在 Controller、Service、前端页面中。

后期想改权限规则时,根本不知道哪里写了判断。


2. 角色和代码强绑定

代码里写死:

admin manager userType == 1

以后角色变了,代码也要跟着改。


3. 不适合后台动态配置

企业后台经常需要在页面上配置:

给张三分配运营角色 给李四分配财务角色 给王五取消删除权限

如果权限写死在代码里,后台根本没法动态管理。


4. 容易产生安全漏洞

某个接口忘了判断权限,用户就可能越权访问。

例如普通用户直接请求:

DELETE /order/1001

如果后端没做权限校验,就会出现严重安全问题。

所以企业系统不会到处写if(admin)

而是会设计一套统一的权限模型。

这就是 RBAC。


四、RBAC 到底是什么?

RBAC 全称是:

Role-Based Access Control

中文叫:

基于角色的访问控制

它的核心思想是:

用户不直接绑定权限,而是通过角色获得权限。

也就是说:

用户 ↓ 角色 ↓ 权限

例如:

张三 ↓ 运营角色 ↓ 商品管理、订单查询、活动配置
李四 ↓ 财务角色 ↓ 财务报表、订单金额、发票管理

这样做的好处是:

权限不直接绑在人身上,而是绑在角色上。

用户只要分配角色,就自动拥有角色对应的权限。


五、RBAC 的三个核心对象

RBAC 里最核心的三个对象是:

用户 角色 权限

1. 用户:User

用户就是系统中的具体账号。

例如:

张三 李四 王五 admin

用户是登录主体。

认证阶段解决的是用户是谁。


2. 角色:Role

角色是一组权限的集合。

例如:

超级管理员 运营人员 财务人员 客服人员 普通员工

角色不是具体的人,而是一类职责。


3. 权限:Permission

权限表示某个具体操作能力。

例如:

user:add user:delete order:list order:detail order:delete report:export system:config

权限越细,控制越精确。


六、用户、角色、权限之间的关系

RBAC 的关系一般是:

一个用户可以有多个角色 一个角色可以分配给多个用户 一个角色可以拥有多个权限 一个权限可以分配给多个角色

所以关系如下:

User ↓ UserRole ↓ Role ↓ RolePermission ↓ Permission

这是典型的多对多关系。

例如:

张三 ↓ 运营角色 + 客服角色 ↓ 订单查询 + 商品编辑 + 售后处理

张三可以同时拥有多个角色。

系统最终判断的是:

张三拥有的所有角色 ↓ 这些角色对应的所有权限

七、RBAC 常见数据库表设计

一个基础 RBAC 权限模型,通常会有这些表。

sys_user sys_role sys_permission sys_user_role sys_role_permission

1. 用户表:sys_user

CREATE TABLE sys_user ( id BIGINT PRIMARY KEY, username VARCHAR(64), password VARCHAR(255), status TINYINT, create_time DATETIME );

用户表保存账号基础信息。


2. 角色表:sys_role

CREATE TABLE sys_role ( id BIGINT PRIMARY KEY, role_code VARCHAR(64), role_name VARCHAR(64), status TINYINT, create_time DATETIME );

例如:

role_code = ADMIN role_name = 超级管理员

3. 权限表:sys_permission

CREATE TABLE sys_permission ( id BIGINT PRIMARY KEY, permission_code VARCHAR(128), permission_name VARCHAR(64), permission_type TINYINT, parent_id BIGINT, path VARCHAR(255), create_time DATETIME );

这里有几个关键字段:

字段含义
permission_code权限标识
permission_name权限名称
permission_type权限类型
parent_id父级权限
path菜单路径或接口路径

4. 用户角色表:sys_user_role

CREATE TABLE sys_user_role ( id BIGINT PRIMARY KEY, user_id BIGINT, role_id BIGINT );

表示用户拥有哪些角色。


5. 角色权限表:sys_role_permission

CREATE TABLE sys_role_permission ( id BIGINT PRIMARY KEY, role_id BIGINT, permission_id BIGINT );

表示角色拥有哪些权限。


八、菜单权限、按钮权限、接口权限

企业后台权限通常不只是“能不能登录”。

它一般分成三类:

菜单权限 按钮权限 接口权限

有些系统还会加上:

数据权限

1. 菜单权限

菜单权限控制的是:

用户能不能看到某个菜单

例如:

用户管理 订单管理 财务报表 系统设置

运营人员可能看不到“财务报表”。

普通员工可能看不到“系统设置”。

这就是菜单权限。


2. 按钮权限

按钮权限控制的是:

用户能不能执行某个页面操作

例如订单页面里有这些按钮:

新增订单 删除订单 导出订单 审核订单

某个用户可以查看订单列表,但不能删除订单。

这就是按钮权限。


3. 接口权限

接口权限控制的是:

用户能不能调用某个后端接口

例如:

GET /order/list POST /order/add DELETE /order/{id} POST /order/export

前端隐藏按钮只是体验优化。

真正安全必须靠后端接口权限。

因为用户可以绕过前端,直接调用接口。

所以企业项目中必须记住一句话:

前端控制显示,后端控制安全。


4. 数据权限

数据权限控制的是:

用户能看到哪些数据

例如:

销售只能看自己的客户 部门经理能看本部门客户 区域经理能看整个区域客户 总部管理员能看全部客户

菜单、按钮、接口控制的是“能不能操作”。

数据权限控制的是“能操作哪些数据”。

这是企业系统里最容易复杂的地方。


九、权限标识怎么设计?

权限标识一般会设计成字符串。

例如:

user:list user:add user:update user:delete order:list order:detail order:export system:config

这种格式好处是清晰。

一般遵循:

模块:操作

例如:

user:add

表示:

用户模块的新增权限
order:export

表示:

订单模块的导出权限

这样前后端都容易理解。


十、登录后权限怎么加载?

用户登录成功后,系统一般会加载用户权限。

流程如下:

用户登录 ↓ 查询用户信息 ↓ 查询用户角色 ↓ 查询角色权限 ↓ 生成权限集合 ↓ 放入 LoginUser ↓ 生成 Token

例如:

LoginUser loginUser = new LoginUser(); loginUser.setUserId(user.getId()); loginUser.setUsername(user.getUsername()); loginUser.setPermissions(permissionSet);

权限集合可能是:

[ "user:list", "user:add", "order:list", "order:export" ]

后续访问接口时,系统就可以判断:

当前用户是否拥有某个权限

十一、Spring Security 中如何使用权限?

在 Spring Security 中,权限最终会放到:

Authentication

里面。

例如:

List<GrantedAuthority> authorities = permissions.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList());

然后创建认证对象:

UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( loginUser, null, authorities );

最后放入:

SecurityContextHolder.getContext().setAuthentication(authentication);

这样 Spring Security 就知道当前用户有哪些权限。


十二、接口上如何做权限控制?

常见做法是使用注解。

例如:

@PreAuthorize("hasAuthority('order:export')") @PostMapping("/order/export") public void exportOrder() { // 导出订单 }

含义是:

只有拥有 order:export 权限的用户 才能调用这个接口

再比如:

@PreAuthorize("hasAuthority('user:delete')") @DeleteMapping("/user/{id}") public void deleteUser(@PathVariable Long id) { // 删除用户 }

这样,权限控制就集中在接口入口处。

而不是在业务代码里到处写:

if (isAdmin) { }

这就是企业项目更推荐的方式。


十三、前端如何使用权限?

后端返回用户权限集合:

{ "permissions": [ "user:list", "user:add", "order:list", "order:export" ] }

前端根据权限控制菜单和按钮显示。

例如:

有 user:list 显示用户管理菜单 有 order:export 显示导出按钮

但是要注意:

前端权限控制只是为了用户体验,不是安全边界。

真正的安全边界一定在后端。

因为前端代码可以被调试、篡改、绕过。


十四、RBAC 和 JWT、Redis 的关系

前面我们讲了 JWT 和 Redis。

这里再把关系串起来。

JWT 负责:

证明你是谁

Redis 负责:

控制你的登录态是否有效

RBAC 负责:

判断你能干什么

它们不是互相替代关系。

而是分工不同。

JWT:身份认证 Redis:会话控制 RBAC:权限授权

完整流程是:

用户登录 ↓ 认证成功 ↓ 加载角色和权限 ↓ 生成 Token ↓ 请求接口 ↓ 校验 Token ↓ 检查 Redis 会话 ↓ 检查接口权限 ↓ 执行业务

十五、RBAC 能解决所有权限问题吗?

RBAC 很常用,但它不是万能的。

它适合解决:

谁能访问什么功能 谁能点击什么按钮 谁能调用什么接口

但是面对复杂数据权限时,RBAC 往往不够。

例如:

只能看本部门数据 只能看自己创建的数据 只能看所在城市的数据 只能看负责客户的数据

这时候通常会在 RBAC 基础上继续扩展数据权限。

例如:

角色 + 部门 角色 + 数据范围 角色 + 租户 角色 + 组织树

所以企业系统常见做法是:

RBAC 解决功能权限,数据权限单独扩展。


十六、常见权限模型演进

一个企业后台权限系统通常会经历几个阶段。

第一阶段:写死管理员判断

if (isAdmin) { // 允许操作 }

适合 Demo,不适合企业项目。


第二阶段:角色判断

if (hasRole("ADMIN")) { // 允许操作 }

比写死用户好,但仍然不够灵活。


第三阶段:权限点判断

@PreAuthorize("hasAuthority('order:export')")

这是企业系统更常见的方式。


第四阶段:RBAC + 数据权限

角色控制功能 数据权限控制数据范围

这是成熟企业后台常见方案。


十七、面试怎么回答 RBAC?

如果面试官问:

RBAC 是什么?

可以这样答:

RBAC 是基于角色的访问控制模型。

它的核心思想是:

用户不直接绑定权限 而是通过角色获得权限

基本关系是:

用户 - 角色 - 权限

一个用户可以有多个角色,一个角色可以拥有多个权限。

企业系统通常会用 RBAC 来实现菜单权限、按钮权限和接口权限。

在后端实现上,一般会设计用户表、角色表、权限表、用户角色关联表、角色权限关联表。

登录时加载用户权限,接口访问时通过 Spring Security 或自定义注解进行权限校验。

需要注意的是,RBAC 主要解决功能权限,复杂的数据权限通常需要在 RBAC 基础上继续扩展。


十八、最终核心理解

到这里,我们可以把认证和授权彻底区分开。

认证解决的是:

你是谁

授权解决的是:

你能干什么

JWT、Redis、Spring Security、Gateway 主要帮助我们完成认证链路和统一鉴权入口。

而 RBAC 解决的是企业系统里的权限分配问题。

它通过:

用户 ↓ 角色 ↓ 权限

把复杂权限管理抽象成一个可配置、可维护、可扩展的模型。

所以企业系统普遍使用 RBAC,不是因为它高级,而是因为它足够稳定、清晰、可维护。

对于大多数后台系统来说,RBAC 是权限体系的基础。


下篇预告

下一篇我们继续:

《企业认证与安全体系(九):单点登录 SSO 到底是怎么实现的?一篇讲透企业统一身份认证》

前面我们已经讲了:

JWT Redis Gateway OAuth2 RBAC

下一篇开始进入企业多系统登录问题。

我们将讲透:

什么是 SSO 为什么企业需要单点登录 多个系统如何共享登录态 SSO 和 OAuth2、OIDC 是什么关系 统一身份认证平台如何设计 为什么登录一次可以访问多个系统

真正把企业统一身份认证体系串起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询