V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
LPJD
V2EX  ›  程序员

如何设计一个前后端分类管理系统的权限管理?

  •  
  •   LPJD · 2023-10-25 18:26:27 +08:00 · 2196 次点击
    这是一个创建于 419 天前的主题,其中的信息可能已经有所发展或是发生改变。
    看了若依的那种菜单管理,感觉很鸡肋。看过很多管理系统的权限模块都这样设计,有什么优点吗?还是大家都只是抄老旧的设计方案?

    若依的菜单管理:
    新增:填写:权限标志,组件路径。这两个参数都是和代码有关的,只能问写代码的人要,也不能乱填(代码改了还得同步修改数据库),可以说是在 UI 界面配置硬编码的值。写错了还会不能用。

    修改:支持修改排序、显示/隐藏菜单。这个感觉也用不上,显示/隐藏菜单在角色-权限功能已经有了。修改排序:没人会想去调整目录的排序吧,项目上线后就固定了。

    删除:更加用不上了,要是误删除了整个功能都用不了。还得找备份数据恢复。

    这种菜单管理的,开发人员直接写在配置文件,或者数据库不就好了吗。前端整个页面处理配置,还得登陆超管账号上去配置。上了生产后,登录超管账号还得找运维,麻烦的很。

    若依的菜单管理:
    21 条回复    2023-10-26 23:09:01 +08:00
    gowk
        1
    gowk  
       2023-10-25 19:13:51 +08:00   ❤️ 1
    问了我一直想问的问题,感觉菜单只能是开发人员自己调整,完全可以做成配置文件,不用开发 UI 界面
    drupal
        2
    drupal  
       2023-10-25 19:18:15 +08:00   ❤️ 1
    权限管理缺少鸡肋.
    有无兴趣参与搭轮子?
    计划用 Java 21,Spring cloud 3.1,采用目前 LTS 的版本重构一套.
    目标是完全开源
    darkengine
        3
    darkengine  
       2023-10-25 19:52:11 +08:00
    删除一般都是软删除
    yeqizhang
        4
    yeqizhang  
       2023-10-25 20:35:18 +08:00 via Android
    没啥问题。
    菜单除了 springmvc 跳转的页面,还有直链等类型,这个总要提供在后台配置吧,既然要做这个,干脆就都在后台系统配。至于功能按钮,要给角色、用户绑定权限的,至少查询展示少不了,那也把增删改也放一块呗。这些是我个人的分析哈
    ikas
        5
    ikas  
       2023-10-25 20:43:12 +08:00   ❤️ 1
    1.权限标志,只是资源的一种友好标识符而已,这菜单也只是资源的一种
    2.菜单的管理与权限本身没有什么关联,对菜单的管理操作不过是后台管理系统中的基本功能(很多客户要求自行配置菜单的)
    3.资源,比如某个 api 对应的后端方法,这个通常只能由后端定义
    4.它这里菜单添加了权限标志,只是为了权限框架统一管理

    国内后端常见的权限模型:
    Resource-Based Access Control
    Role-Based Access Control
    gransh
        6
    gransh  
       2023-10-25 20:52:52 +08:00   ❤️ 1
    本来出发点是开发人员只挣开发的钱,懒得维护,培训一下甲方运维之后大部分情况就能当甩手掌柜的。
    如果写配置文件或者数据库,可以说你一年有大半时间都在跟客户沟通和改配置文件上了。
    summerLast
        7
    summerLast  
       2023-10-26 09:53:01 +08:00
    后台注解 直接扫描生成资源权限相关的的接口
    lyxxxh2
        8
    lyxxxh2  
       2023-10-26 09:55:13 +08:00
    我没看多"若依" 但是我知道他存在数据库。

    rbac 动路由,这不是很合理吗?

    新增和删除,肯定只有技术员才能用啊, 大不了你可以隐藏起来。

    ***
    写在配置文件: 用户想新增个 "出货员" 角色,叫开发者来?
    写在数据库: 现在不就是数据库。
    yanhuamiluan
        9
    yanhuamiluan  
       2023-10-26 10:34:04 +08:00
    基于角色的访问控制, 若依实现了这一个逻辑, 有啥问题
    改个配置就要超管账号, 那是授权问题
    sketcherly
        10
    sketcherly  
       2023-10-26 11:00:16 +08:00
    @drupal 有具体想法吗
    LPJD
        11
    LPJD  
    OP
       2023-10-26 13:49:35 +08:00
    @ikas 关于 Resource-Based Access Control 模式,各种博客和技术文章的说法不一样,我曾经困惑了很久,和朋友研究了一个星期,直到看见了 stack overflow 的回答:
    https://stackoverflow.com/questions/18435219/resource-based-access-control-vs-role-based-access-control

    Resource-Based Access Control 这个名词出自于一个国外程序员写的一篇博客中( stackoverflow 的问题给出了原文地址),这个程序员自己定义的一个新名词,而且只有他自己一个人在用,不是通用模型。我看了那篇博客原文,Resource-Based Access Control 所定义的内容,就是 RBAC(role-based-access-control)的具体实现。而 RBAC(role-based-access-control)是 NIST 定义的标准,是一个理论模型。中文资料中关于 Resource-Based Access Control 的定义要么是翻译了原文,要么是在原文基础上二次修改。英文资料已经找不到关于 Resource-Based Access Control 的定义了,博客原文都打不开了。虽然我们常用的权限系统的设计和那篇博客的所描述的内容大同小异,但我不建议使用 Resource-Based Access Control 这个词,这个词和 RBAC 放一起容易混淆,而且找不到关于这个名词的标准定义。

    常用的关于权限系统的设计模型有两个(维基百科英文版给出了很详细的描述)
    ACL(Access control list):用户、权限。用户名下直接挂权限,优点:灵活。缺点:要给每个用户都设置权限,繁琐。
    RBAC:用户、角色、权限。用户名下挂角色,角色名下挂权限。优点:简化了给用户设置权限的步骤,满足的大部分业务场景。缺点:灵活性稍微低一点

    现在业务系统几乎都是基于 RBAC 设计权限。除非客户强制提需求:“我就不想新增一个角色,就想单独改一个人的权限”,特殊情况下才用 ACL 。

    前后端分离的情况下,权限管理被分割成了两部分:
    1. UI 界面组件的显示权限(也称为菜单权限、按钮权限、目录权限等)
    2. 服务器 API 的访问权限(也称为资源权限 resource )

    当给一个用户授权某个功能的使用权时,至少需要授予两个权限:UI 组件权限、API 访问权限(这个组件所访问的 api )

    从理论模型分析:功能 = UI 权限 + API 权限

    从用户的角度看授权,进一步被简化成了:功能 = 权限
    LPJD
        12
    LPJD  
    OP
       2023-10-26 14:32:36 +08:00
    @drupal 我已经搭建一套权限系统了,使用 SpringBoot 3.0.2/2.7 + SpringCloude Gateway ,JDK17 和 JDK8 的版本都有。前后端都做好了。也已经放到 github 了开源了。创建用户,单点登陆 / 退出登陆、前端动态路由、用户授予角色,角色授予权限,后台 API 鉴权等都做好了。目前还没写文档。想看看别人怎么做的,目前见得最多得是类似若依那一套经典权限系统设计。

    关于技术选型:使用 JDK21 只能在一些生命周期短小项目跑。新出的 JDK 都不稳定,需要 2-3 年时间才能稳定,没啥兴趣。现在 JDK17 也只是小规模试用。我尝试新项目使用 JDK17 ,结果偶尔会遇到一些三方工具包,或三方工具不支持,只支持到 JDK8 ,每次遇到这种问题都得浪费我 1-2 个小时去处理。使用 JDK17 让我感觉到自己在浪费青春。旁边的 JDK8 沉淀了大量成熟的开源工具,很多都没支持 JDK17 。对于上班搬砖的人来说,使用 jdk8 是最舒服。另外 SpringBoot 3.1 也是半成品,用过 Springboot 3.1.2 ,结果日志打印提示,一些 spring 自家的组件都不支持 3.1.2 ,还建议我用上一个版本的 springboot ,然后我又退回 springboot3.0.2 了
    drupal
        13
    drupal  
       2023-10-26 14:52:59 +08:00
    @LPJD 发个链接,学习一下。
    Jrue0011
        14
    Jrue0011  
       2023-10-26 16:40:50 +08:00
    理论其实就那么些,主要看实现吧。谷歌不是有篇论文讲他的权限系统 Zanzibar ,定义了一些语法来表达 ACL 权限,也有组成员(就类似角色)、交并集、继承之类的能力,而且现在好像也有几个基于这篇论文的开源实现了
    ikas
        15
    ikas  
       2023-10-26 19:29:06 +08:00
    那些模型只是参考,基本都是混合一起..
    我目前常用的方式:
    资源: 接口,按钮,菜单等等都是资源, 设计一张资源表,然后菜单表中关联资源 id,其它也是
    角色,用户组,或者是用户: 这些与资源关联,关联关系还有计算模式(比如+,-)
    用户与角色等关联,这个没什么说的

    不管是计算菜单还是其它均是只有一个入口,就是获取其所属资源列表,然后再去关联

    根据业务,客户要求, 资源的关联方可以灵活选用,比如只使用角色
    LPJD
        16
    LPJD  
    OP
       2023-10-26 20:31:52 +08:00
    @ikas
    菜单表是怎么设计的?存放什么数据?

    前后端分离后,按钮,菜单这些数据感觉就没用了。后台完全用不上。菜单和资源的关联关系,也只有前端自己使用,如果存数据库的话,每次登录,前端都得到后台拉一遍这些数据。同时这些数据都是代码相关的数据,值固定不能改,存数据库感觉没有意义了。我现在的项目,这些菜单数据、菜单相关的资源,菜单和菜单资源的关联关系全部丢给前端自己写死在代码里面了。后台只关系用户拥有的角色、角色拥有的接口权限。其他一律不管。至于个人拥有哪些菜单、菜单资源,后台给个 text 字段,前端自己随意传数据到数据库持久化。
    ikas
        17
    ikas  
       2023-10-26 21:08:20 +08:00
    前后端分离与这些没有任何关系.

    很多后端系统,比如金融证券行业的系统,客户都是要完全自己配置的,菜单 url 也不一定是自己系统的(所以要可以新增,修改),不能再搞一套关系表来配置这些

    重点是基于资源统一管控这些
    LPJD
        18
    LPJD  
    OP
       2023-10-26 21:19:46 +08:00
    @drupal
    JDK8 版本的,master 分支是 JDK17 版本,没有维护了,代码比较旧。JDK8 版本是从 JDK17 版本转过来的,然后重构的项目,简化了逻辑。
    https://gitee.com/LuPangJieDeng/base23-spring-cloud/tree/JDK-8
    LPJD
        19
    LPJD  
    OP
       2023-10-26 21:25:28 +08:00
    @ikas 原来如此,了解。我公司做的都是自家的产品,用户比较小。菜单配置 url 这些,后端管理的一段时间,后来嫌麻烦,新项目后端都不管理,前端也不配置了。
    LPJD
        20
    LPJD  
    OP
       2023-10-26 21:29:05 +08:00
    @drupal 我那个只是 Demo ,我公司在用这种模式。像若依那种才是主流的方案吧。比较这么系统都是这样设计的,有它存在的意义。我们公司一开始也是用主流的方式,后来嫌步骤繁琐,就简化了。
    ikas
        21
    ikas  
       2023-10-26 23:09:01 +08:00
    看了下源码,可能这个比较适合你们公司业务
    如果要设计一个通用的,还是要改动的,将资源抽离,仅保留权限标志

    比如 shiro 的权限检查
    https://shiro.apache.org/java-authorization-guide.html

    ```
    String perm = "printer:print:laserjet4400n";

    if(currentUser.isPermitted(perm)){
    //show the print button?
    } else {
    //don’t show the button?
    }
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5366 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 06:53 · PVG 14:53 · LAX 22:53 · JFK 01:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.