RBAC 和企业后台常见的数据权限有什么区别?
RBAC 解决的是功能权限,即用户能不能进入某个菜单或调用某个接口;数据权限解决的是可见范围,即进入之后能看到哪些行、哪些列。很多系统第一版只做了功能权限,等业务方提出「不同区域的运营只能看自己区域的数据」时,才发现数据权限没有设计位置。二者应分开配置、分开演进,角色描述「能做什么」,数据权限描述「能对谁做」。
权限模块很少在立项时被重视,却常在项目后期以事故的形式暴露。这篇文章把企业后台的权限拆成功能权限与数据权限两个层次,讲清楚 RBAC 的常见误用、数据权限的落地方式、多组织层级的处理,以及越权防护与权限审计该怎么做。
权限模块几乎不会成为立项时的焦点。多数企业后台在需求阶段把注意力放在业务流程、报表和交互上,权限往往被压缩成一句「按角色控制」放在需求清单的末尾。等到系统上线、用户角色变多、组织架构调整、审计提出要求时,权限才第一次以「事故」的形式进入视野——某个人看到了不该看的数据、某个审批越过了层级、某个离职账号还留着入口。
这类问题的根源,通常不是写代码的人不小心,而是权限模型在一开始就没有被当成一个有独立设计对象的数据结构来对待。它被当成了散落在各个接口里的 if 判断,而不是一套可配置、可审计、可回溯的模型。
这篇文章讨论的是企业后台(管理端、运营端、监管端)的权限模型设计,重点在两个层次:一是我们熟悉的「功能权限」,即用户能不能进入某个菜单、调用某个接口;二是更容易被低估的「数据权限」,即用户能看到哪些范围的数据。二者合起来,才构成一个完整的权限边界。相关的分层设计思路可以参考 技术能力 与 工程与质量保障 中的说明。
RBAC(Role-Based Access Control,基于角色的访问控制)是企业后台里使用最广的权限模型。它的核心思想很朴素:不把权限直接授予用户,而是授予角色,用户通过角色获得权限。拆开看是四张表:
这个结构本身没有问题,问题几乎都出在落地方式上。下面几种误用,在项目中出现的频率很高。
最初角色只有三五个:管理员、运营、财务、客服。随着业务发展,每个部门都想有点自己的特殊权限,于是出现「运营-华东」「运营-华东-临时」「客服-主管」「客服-主管-带审核权」这样的角色,数量迅速膨胀到几十上百个。
角色爆炸带来的直接后果是维护困难:一个新功能上线,要判断给哪些角色加权限,没人说得清楚;一次组织调整,要改几十个角色,容易漏改。更深层的问题是,当角色数量增长到一定程度,它其实退化成了「一个角色对应一个人」,RBAC 的复用价值消失了。
缓解办法是区分两类角色:一类是职责角色,按岗位职责划分,数量有限且相对稳定;另一类是临时授权,用于处理短期、例外的情况,有明确的生效期与到期回收机制。不要把例外长期沉淀成新角色。
岗位是组织管理上的概念,角色是权限上的概念,二者不总是一一对应。同是「区域经理」,负责不同区域、不同业务线时,需要的数据权限可能完全不同。如果把权限直接绑在岗位上,一旦组织调整,权限就得跟着大改。
更稳的做法是把「能做什么」和「能对谁做」拆开。角色描述「能做什么」(功能权限),数据的可见范围由独立的数据权限规则描述。这样组织调整时只改数据归属,不动角色定义。
另一种常见做法是在接口里直接判断用户身份,例如判断当前用户是否是某个固定账号、是否属于某个硬编码的部门。这种做法在项目初期很快,但在后期几乎无法维护:新增角色要改代码、发版,权限调整无法通过配置完成,也无法生成一份「谁有什么权限」的清单交给审计。
权限判断应当收敛到一个统一的鉴权层,接口只声明「需要什么权限」,由鉴权层决定「当前用户有没有」。这样权限的定义可以入库、可以配置、可以导出,也可以被审计。
功能权限解决的是「能不能进这个页面、能不能调这个接口」,数据权限解决的是「进去之后能看到哪些行、哪些列」。很多系统的第一版只做了功能权限,等到业务方提出「不同区域的运营只能看自己区域的数据」时,才发现数据权限没有设计位置。
按可见范围的确定方式,数据权限大致可以分为四类:
这四类往往需要在同一个系统里共存,而且要能按「角色 + 资源」的组合分别配置。例如同一个用户在订单资源上是「本部门」,在报表资源上是「自定义范围」。
数据权限有两个维度:
列级控制容易被遗漏。一个系统如果在行级做了严格隔离,但把所有字段都返回,那么获得任意一条记录的人就能看到全部敏感字段。列级控制应当与脱敏策略一起设计,而不是在前后端各自判断。
数据权限的求值位置决定了它的可靠性。如果只在应用层拼装查询条件,那么任何绕过应用层直接查库的入口(导出任务、定时报表、内部工具)都可能绕过数据权限。稳妥的做法是把数据权限作为数据访问层的一部分统一注入,让所有查询——无论是页面查询、导出还是异步任务——都经过同一套过滤逻辑。
集团或连锁类企业后台最大的特点是组织是有层级的:集团、区域、子公司、门店,层层向下。权限模型必须能表达这种层级,否则就只能用「每个人配一遍」的笨办法。
基础工作是给每条业务数据标注它归属的组织节点。这个归属应当在数据产生时就确定下来,而不是事后靠部门字段去猜。归属字段一旦缺失或不一致,上层的「本部门及下级」过滤就无法正确计算。
组织树还需要考虑组织调整的历史。一个部门被拆分或合并后,历史数据仍归原组织,还是随调整一起迁移?这需要业务上给出一致规则,并在实现上保留组织树的变更历史,避免出现「数据归属指向一个已经不存在的节点」。
授权本身也有作用域。同一条权限规则,在集团层配置表示「适用于全部下级」,在某个子公司配置表示「仅适用于该子公司」。如果不区分作用域,就会出现两种错误:子公司管理员改动了集团级的通用配置,或者集团统一配置无法被下级覆盖。
常见做法是把授权规则分为继承与覆盖两类:下级默认继承上级规则,需要时可以在本层增加更严格或更宽松的规则,并明确指出哪些层的配置可以覆盖上级。
越权是权限系统最典型的失效形式,通常分为两类:
防护的核心原则是服务端不信任客户端传来的任何身份与范围信息。所有「我是谁」「我能看谁」的判断都必须在服务端从登录态推导,而不是从请求参数里读取。对于按 ID 访问的资源,需要在返回前校验该资源是否落在当前用户的数据权限范围内。
另一个常见疏漏是接口与页面权限不一致:页面隐藏了按钮,但接口没有校验,导致越权可以通过直接调接口完成。功能权限的校验必须放在接口层,页面隐藏只是体验优化,不是安全措施。
权限系统不只是「配置」,还需要「留痕」。审计要能回答三个问题:谁在什么时候获得了什么权限、谁在什么时候使用了什么权限、权限的变更由谁发起、依据是什么。
实现上建议至少保留两张日志:
审计日志本身也要受保护:不能被普通管理员删除或修改,且保留期限要符合行业要求。对于监管、医疗这类场景,留痕往往不是「可选项」而是硬性要求,具体可以参见 行业解决方案 中对应场景的说明。
如果要把上面的内容收敛成可执行的建议,可以按下面的顺序推进。
第一步,先把权限定义成数据。 权限点、角色、数据权限规则都应当入库、可配置、可导出,而不是散落在代码里。这一步是所有后续工作的前提。
第二步,区分功能权限与数据权限。 功能权限描述「能做什么」,数据权限描述「能对谁做」,二者分开配置、分开演进。
第三步,把鉴权收敛到统一入口。 所有接口经过同一个鉴权层,数据权限作为数据访问层的一部分统一注入,避免出现绕过路径。
第四步,设计好组织层级与作用域。 明确授权规则的继承与覆盖关系,让集团与下级都能配置,同时不互相干扰。
第五步,把审计做进第一版。 权限变更日志与敏感操作日志不要留到二期,否则会失去大量历史痕迹。
完整的项目推进方式与各阶段产出物,可以参考 交付流程;如果你对权限模型中的具体取舍还有疑问,也可以先看看 常见问题 里的相关条目。
权限模型的难点,不在于技术上的复杂度,而在于它是否可以配置、是否可以随组织变化而调整、是否可审计。一个设计得好的权限系统,在业务变化时表现为「改配置」,在设计得不好的系统里则表现为「改代码加发版」,甚至表现为一次数据泄露。
回到最初的问题:权限不该是项目末尾补上的一块逻辑,而应当是贯穿数据模型、接口设计、组织关系的一条主线。把它当成主线来设计,后期的维护成本会明显低于把它当成补丁。
广州科芃科技有限公司技术团队在企业后台与行业系统的开发中,会把权限模型作为方案评估的固定环节,先确认组织层级、数据归属与审计要求,再决定功能与数据权限的配置方式。相关能力说明见 软件研发服务。
RBAC 解决的是功能权限,即用户能不能进入某个菜单或调用某个接口;数据权限解决的是可见范围,即进入之后能看到哪些行、哪些列。很多系统第一版只做了功能权限,等业务方提出「不同区域的运营只能看自己区域的数据」时,才发现数据权限没有设计位置。二者应分开配置、分开演进,角色描述「能做什么」,数据权限描述「能对谁做」。
角色膨胀通常是因为把例外情况长期沉淀成了新角色。缓解办法是把角色分成两类:一类是职责角色,按岗位职责划分,数量有限且相对稳定;另一类是临时授权,用于短期、例外情况,有明确的生效期与到期回收机制。同时把「能做什么」与「能对谁做」拆开,组织调整时只改数据归属,不动角色定义。
水平越权是用户通过修改请求参数访问到他人的数据,例如把订单 ID 换成别人的;垂直越权是低权限用户直接访问高权限接口。防护的核心原则是服务端不信任客户端传来的任何身份与范围信息,所有判断都从登录态推导;对按 ID 访问的资源,返回前要校验是否落在当前用户的数据权限范围内。功能权限的校验必须放在接口层,页面隐藏按钮只是体验优化。
如果只在应用层拼装查询条件,任何绕过应用层直接查库的入口,例如导出任务、定时报表、内部工具,都可能绕过数据权限。稳妥做法是把数据权限作为数据访问层的一部分统一注入,让页面查询、导出与异步任务都经过同一套过滤逻辑,避免出现绕过路径。
基础工作是给每条业务数据标注它归属的组织节点,归属在数据产生时就确定,而不是事后靠部门字段去猜。授权本身也要区分作用域:把规则分为继承与覆盖两类,下级默认继承上级规则,需要时可在本层增加更严格或更宽松的规则。同时保留组织树的变更历史,避免数据归属指向一个已经不存在的节点。
至少保留两张日志:权限变更日志,记录角色与授权规则的增删改,含操作人、时间与变更前后内容;敏感操作日志,记录关键数据的访问与导出行为,尤其是批量导出。审计日志本身也要受保护,不能被普通管理员删除或修改,保留期限应符合行业要求。监管、医疗等场景中留痕往往是硬性要求。