00后系列-00后浅学权限系统设计

推荐专栏:00后-前端学习专栏

1. 00后系列-00后学react hooks

2. 00后系列-00后手写一个js打包器

3. 00后系列-00后浅学Vite热更新

4. 00后系列-00后学习rollup plugin

5. 00后系列-00后项目性能优化经验

6. 00后系列-00后从 0 到 1 手写 Vue3 响应式

7. 00后系列-00后手写Promise之道

8. 00后系列-00后深入理解 React 和 Vue 的 diff 原理

9. 00后系列-00后浅学权限系统设计

前言

  • 基于 Node.js 开发后台管理系统的浅薄经验。

  • 本文主要介绍的是最为普及的权限设计模型是 RBAC模型 ,也就是基于 角色

    • 访问控制 (Role-Based Access Control)。
  • 文章废话较多,可以当乐子看。

浅谈 RBAC 理论

  • 简单来说,角色的本质就是用户权限的集合,用户权限就是用户执行相应职责所需要的访问级别。
  • 比如,系统开发者拥有最高权限,可以看到所有的页面,普通用户只能看到每一个特定角色下的单个页面。
  • 当普通用户由于晋升或者部门调动,需要负责更多的页面,那么原先的特定角色就不适合他了。
  • 这时,基于 RBAC 理论,系统应该赋予这个用户新的角色,而不是直接改动用户的权限集合。
  • 在一个稳定的组织中,每个角色对应的用户权限是相对稳定的,即使某个角色对应权限需要修改,也比一个个去修改一批用户的权限要省事得多。

学习RBAC理论模型

RBAC(基于角色的访问控制)有四种模型,具体选用哪种权限模型要根据组织的需求、安全性要求和系统架构来决定。

理论模型

  • RBAC0(基础模型):这是最基本的模型,应该也是最常见的RBAC模型。包含三个元素:用户、角色和权限。设计基于"多对多"原则,即多个用户可以具有相同的角色,一个用户可以具有多个角色。同样,您可以将同一权限分配给多个角色,也可以将同一角色分配给多个权限。
  • RBAC1(角色分层模型):在基础模型的基础上添加了第四个组件-层次结构,它定义了不同角色之间的资历关系。通过允许高级角色自动获取下级角色的权限,可以消除冗余,例如在角色重叠时必须指定某些权限。
  • RBAC2(角色限制模型):为了在存在利益冲突策略的情况下提供帮助,将根据用户分配添加角色之间的关系。例如,作为一个角色的成员的用户将无法被指派为具有利益冲突的角色的成员。
  • RBAC3(统一模型):与RBAC2一样,RBAC3限制了可用的用户权限,但基于不同的上下文。例如,根据会话期间执行的任务,用户可能需要不同级别的访问,RBAC3限制会话期间激活的权限。

案例分享

  1. RBAC0(基础模型):假设我们有一个涉及权限的系统,如果按传统权限模型,给每一个用户逐一赋予权限则会非常麻烦,并且做不到批量修改用户权限。这时候,可以抽象出几个角色,譬如 华北的区总、xx 城市负责人等,然后把权限分配给这些角色,再把角色赋予用户。这样无论是分配权限还是以后的修改权限,只需要修改用户和角色的关系,或角色和权限的关系即可,更加灵活方便。
  2. RBAC1(角色分层模型):在RBAC0的基础上,我们可以进一步细化角色。例如,一个公司的华北区总可能是分几个等级的,譬如除了华北区总,还有华北区副总,而华北区副总只有华北区总的部分权限。这时候,我们就可以采用RBAC1的分级模型,把华北区总这个角色分成多个等级,给华北区副总赋予较低的等级即可。
  3. RBAC2(角色限制模型):有些角色之间是需要互斥的,譬如给一个用户分配了华北区总的角色,就不能给他再赋予华东区总的角色了。这时候,我们就需要采用RBAC2模型,通过增加一些限制来防止这种异常情况的发生。
  4. RBAC3(统一模型):RBAC3模型可以动态地约束用户拥有的角色。例如,一个人如果既是华北区总,又是某个城市负责人的时候,当进入系统页面时,只能选择一个角色身份。

学习总结

  • 真正会被在生产环境实践的理论,往往都不会是最复杂的,而是最合适的。

  • 那么对于企业级的权限系统的设计,什么叫最合适的理论呢? 开发速度贼快、实现方式简单、用户操作简单、理解起来简单、最后还能满足用户需求,这不就是最合适的吗?😄

  • 理论是死的,但人是活的,具体的实现方式可以不完全按照已有的理论模型来。

  • 不存在绝对完美的理论,记得留意理论的自身缺陷。

  • 学会质疑理论的同时,也要学会质疑需求。需求是否合理?这样做有什么收益?开发和维护成本是多少?一定要做吗?能不能换个方式做?能不能先保持现状?这个真的着急做吗?未来有没有可能会改动?这样改动会对现在用户造成什么影响?用户觉得合适吗?开发者的工作量可控吗?......

  • 理论都是人想的,你也可以自己想个更合适的。

问题拷打环节

下面,我就当读者已经达到以下境界。

  • 知道 RBAC理论模型 是啥。
  • 会写代码。
  • 准备基于这套理论模型大展身手。

假设我是 一个 爱找你茬 的同事(友情提示,不要自行脑补),想拷打你几个问题。

问题1

问题1: 你是不是闲的? 整个角色的概念出来有什么用?

你别说,你别说,还真有可能,听完第一个问题,你就倒下了。

有没有一种可能,你的系统没几个人用。

有没有一种可能,你的系统也没几个界面。

有没有一种可能,只有你开发时需要看所有页面,其他人最多看某一个界面。

有没有一种可能,每个人的角色都不一样,你的角色根本没有可以复用的时候?

问题2

假设你经受住了同事的考验,解释了 RBAC模型 的好处,确定了你的系统用 RBAC模型 是有好处的。

下面,我的第2个问题是 你准备用哪个理论模型呢?

基于 万事怎么简单怎么来 原则,你可能会选择最简单的 RBAC0 模型。

问题3

听完你的选择, 我的 问题3 是 你确定你的系统需要做到一个用户有多个角色对应的权限吗?

比如,一共有4个页面,每个页面权限对应一个角色。当某个用户目前只有某一个页面的权限时,他觉得不够,需要所有的页面权限。从系统维护的角度来说,你是选择给用户一个有更多页面权限的新角色,还是选择给用户更多的角色同时合并角色权限呢?

简单来说,两个方案的角色都是对应多个用户。

  • 方案1:是一个用户一个角色,一个角色有多个界面权限和多个用户。
  • 方案2:是一个用户多个角色,每个角色有唯一界面权限和多个用户。

问题4

假设你选了第一种方案,我的 问题4 是 如果需要关闭用户的某个页面权限,你的方案是什么?听起来好像只能给新增一个没有该页面权限的角色,因为你不能改动这个角色原本的权限,这会影响到属于该角色的其他用户。如果这个角色拥有50个页面权限,你算算如果只是为了删除一个用户 1 到 49 个页面权限,产生的新角色有多少的可能性 ?😄

问题5

假设你选了第二种方案,问题4 就不是一个难题了,因为你只需要解除用户与某个页面角色的关系就可以了。

因为这一次你是从基于角色去解除某个用户的界面权限,所以不会影响到其他用户。

那么,我的问题5来了。如果你需要给一批人相同的权限呢? 按方案二的想法,你需要给每个用户都来一遍相同的操作,给每个用户添加更多的角色。如果没有支持批量操作的界面,那这真是一听就很糟糕的设计。

问题6

听完我上面的问题,你可能已经烦躁了,并且表示可以完全支持 多对多 原则,也就是说一个用户有多个角色,一个角色有多个界面的权限,并且这些角色的页面权限是合并的。然而,低情商的我又开始提问了。

问题6: 如果A页面权限是经常变动的,也就是说,你需要经常删除一批人的A页面权限,这时你又该如何去做呢?

因为你不能对用户的拥有A页面权限的角色有任何改动,这会影响到该角色的其他用户,所以你只能选择生成新角色去覆盖老角色的权限?

这听起来是难以维护的,因为这样数据库里奇奇怪怪的角色是会越来越多的。

听到这里,你可能疑惑 RBAC0 理论模型 都实现完了,为什么还会遇到困难呢?首先,不要完全依赖于理论模型,大家都知道的理论模型往往只是应用比较广泛,而不是能解决你应用时 100% 的问题。

为了解决上述的问题,可以让每个页面的权限通过名叫用户组的方式来维护。

用户组的概念是基于 RBAC(基于角色的访问控制)模型的扩展。在RBAC模型中,用户通过角色与权限进行关联,一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成"用户-角色-权限"的授权模型。

然而,当用户数量非常大时,给系统每个用户逐一授权(授角色)是件非常烦琐的事情。这时,就需要给用户分组,每个用户组内有多个用户。除了可给用户授权外,还可以给用户组授权。这样一来,用户拥有的所有权限,就是用户个人拥有的权限与该用户所在用户组拥有的权限之和。

例如,我们可以把一个部门看成一个用户组,如销售部,财务部,再给这个部门直接赋予角色,使部门拥有部门权限,这样这个部门的所有用户都有了部门权限。用户组概念可以更方便的给群体用户授权,且不影响用户本来就拥有的角色权限。这种方式更能贴近实际业务情况,便于用户理解。特别是一定量级的时候,可视性的优势更加明显。总的来说,用户组是用户的集合,角色是权限的集合。

问题7

至此,你觉得现在的设计连批量操作都考虑到了,总不会还有问题吧。

然而,多嘴的我 又要开始提问题了。

问题7: 你想过用户申请权限该怎么做吗? 是根据角色来申请权限吗? 那没有匹配的角色该怎么办呢?

这时,你可能会想每次根据选择申请的页面去创建一个新角色不就行了,但是这样用户量一旦上去,数据库里的角色数岂不是很混乱? 恐怕连每个角色的名字都取不出来吧。

也许,经历拷打后成熟的你,已经可以想到通过页面权限来对角色进行去重操作,如果库里有相应的角色就不用重新生成新角色了。

问题8

可是,你的 好同事我 还是锲而不舍,继续追问道。

问题8: 你的思路是对的,所以让我开始疑惑。比如删除用户的某个页面权限后,我究竟是应该直接修改角色的自身权限,还是说基于现有的页面权限生成新角色去替代老角色,如果可以复用现在已有的角色,是选择复用呢? 还是新建呢?

听到这里,你应该明白了这位多嘴的同事的良苦用心。😂

总结

  • 最好的总结是自己总结,总结好了记得发我一下。【🐶】
  • 任何一个稍微复杂一点的权限系统,在代码开发前都应该尽可能考虑到权限系统在维护时可能遇到的问题,而不是上来就直接开发,把一系列的坑留给未来的自己或接手你代码的开发者。
  • 做事三思而后行,code 依然是如此。
  • 有兴趣的话,可以解答下同事最后的问题。
相关推荐
Tech Synapse9 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
.生产的驴9 分钟前
SpringCloud OpenFeign用户转发在请求头中添加用户信息 微服务内部调用
spring boot·后端·spring·spring cloud·微服务·架构
微信-since8119225 分钟前
[ruby on rails] 安装docker
后端·docker·ruby on rails
Myli_ing27 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风30 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave37 分钟前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
软件小伟39 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j