V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
awesomePower
V2EX  ›  程序员

在多服务系统中,如何对业务数据进行权限校验

  •  
  •   awesomePower · 326 天前 · 1711 次点击
    这是一个创建于 326 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如说有个简单的账号权限表,字段是账号和组织 ID 。然后有若干业务表,业务表里面的每条数据都标记了是和哪个组织 ID 关联的。这些业务表分散在不同的服务中,对每个服务的请求都会有账号信息。

    有没有一种通用且高效的方法,对账号查询或修改业务数据进行权限控制。

    20 条回复    2024-01-13 19:47:16 +08:00
    dode
        1
    dode  
       326 天前
    接收请求的时候检查账号和组织 ID 权限,再决定要不要执行业务逻辑
    awesomePower
        2
    awesomePower  
    OP
       326 天前
    @dode 谢谢解答。但如果是该账号有 2000 个组织 ID 的权限;同时该账号查询了某张业务数据表,需要查询到符合他权限的数据,这种场景有什么好方案处理呢?
    lujiaxing
        3
    lujiaxing  
       326 天前   ❤️ 1
    这个我以前倒是做过. 就是数据权限嘛.
    当时的需求是:
    1. 自己部门的一线员工可以看自己部门的数据.
    2. 上级部门领导可以看本部门以及下属部门的数据. 上级部门的一线员工不可以查看下属部门的数据.
    3. 部门可以临时抽调人员, 临时抽调人员享有跟借调部门一样的数据权限. 同时被抽调人员仍享有自己原属部门的数据权限.

    我当时是这样设计的:
    由于我们的用户表与部门表都存在自增 ID, 那么数据权限就是在每条数据后面增加两个字段: 部门权限, 个人权限.
    全都是 blob 类型, 大端.
    里面按 bit 存储权限. 比如 ID 为 1 的用户可以看, 那么个人权限里的权限二进制值就是 "10000000....000" 即 0x08.
    1 2 3 三个用户可以看, 二进制存储就是 1110. 即 0x0E. 以此类推. 按部门权限查询的时候只需要查到这个用户所属部门, 是否为部门领导即可. 如果是部门领导, 则将本部门与下属部门的数据权限做 OR 运算, 就能得到他能看得到的数据了.
    lujiaxing
        4
    lujiaxing  
       326 天前
    @lujiaxing 是 1000. 不是 10000000....000. 勘误
    dode
        5
    dode  
       326 天前
    @awesomePower

    这样的查询,这几千个组织 ID ,不要用前端传进来,根据这个账号,直接在后台获取一些 ID 列表,硬查呗
    wxw752
        6
    wxw752  
       326 天前
    1.判断查询的这张表是需要权限校验
    2.后端根据用户的 token 拿到所有的组织 id
    3.在查询的 sql 后面自动根据上述组织 id 拼接一个查询条件,in 这些组织 id
    awesomePower
        7
    awesomePower  
    OP
       326 天前
    @lujiaxing 谢谢你提供的思路。那你这个数据权限字段理论上最多支持 65*1024*8 ( 65k )大约 100w 个部门 ID 或者用户 ID ,正常企业肯定是够用了。这种设计下,如果个人变更部门怎么办,是要更新业务数据吗,还是说查询的时候部门权限和个人权限要同时满足
    awesomePower
        8
    awesomePower  
    OP
       326 天前
    @wxw752 过千个组织下,in 的查询效率会降低,业务数据量越大越明显。
    awesomePower
        9
    awesomePower  
    OP
       326 天前
    @dode 硬查的效率不高
    wxw752
        10
    wxw752  
       326 天前
    @awesomePower #8 我们是读写分离的,写入 mysql, 同步进数仓,数仓查这点条件小意思。
    awesomePower
        11
    awesomePower  
    OP
       326 天前
    @wxw752 确实,做查询统计或者报表汇总确实进数仓更好,专业的工具做专业的事
    lujiaxing
        12
    lujiaxing  
       326 天前
    @awesomePower 人员变更不是问题呀.
    部门权限查询的时候是按人所属部门来的. 他就算是换了个部门, 也是按新的部门的权限查. 他的权限在人员组织架构变更的瞬间就已经跟着改了.
    至于人的权限, 人员离职之后人员被标记删除, 这时候他的数据权限归零也好, 留在那也好, 都无所谓了. 反正人都不在了. 新增人员只需要将对应权限增加一个 bit 即可. 嫌麻烦你可以先固定生成一个 100W bit 的二进制数据, 全部填零. 这样就不需要每次都延长数据权限字段数据长度了
    awesomePower
        13
    awesomePower  
    OP
       326 天前
    @lujiaxing 谢谢解答
    wu00
        14
    wu00  
       326 天前
    没有什么是加中间层解决不了的... 一个不行就两个。
    如果你真要做到单行数据粒度级别的权限,比如 productId:1 这条数据 userA 能看不能改;
    最好是引入第三方权限框架做一个访问/数据权限层,比如 casbin 之类的;
    抽离出“每条数据都标记了是和哪个组织 ID 关联”这个东西,集中维护在权限层。
    tramm
        15
    tramm  
       326 天前
    持续关注
    a1392136
        16
    a1392136  
       326 天前
    @awesomePower 一种方案是产品层面解决,以组织为维度,对数据进行操作(限制操作业务数据的组织数)
    另一种方案就是 ABAC 方案进行属性控制,可以参考 csbin 、OASIS XACML 3.0
    jinxjhin
        17
    jinxjhin  
       325 天前
    @lujiaxing #3 请教下,这样对数据做了处理后,查询的时候是直接在数据库上做位运算得到结果?这和直接 in 查询有相比有性能优势吗?
    awesomePower
        18
    awesomePower  
    OP
       325 天前
    @a1392136
    @wu00 谢谢解答和提供方案
    lujiaxing
        19
    lujiaxing  
       325 天前 via Android
    @jinxjhin 是的,直接位运算就可以了。不需要 IN. 单字段运算的线路永远是 IN 所不能比的,尤其 IN 的数量大时候
    lujiaxing
        20
    lujiaxing  
       325 天前 via Android
    @lujiaxing 效率。打错了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1103 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:06 · PVG 03:06 · LAX 11:06 · JFK 14:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.