V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
seyoatda
V2EX  ›  Go 编程语言

RBAC 模型如何定义权限,以及处理的时机?

  •  
  •   seyoatda · 2021-09-01 14:36:54 +08:00 · 1908 次点击
    这是一个创建于 1164 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前用 golang 的 casbin 库来实现 RBAC 模型做基本的权限控制。有几下几点:

    1. 如果需要一个超级管理员,就是那种不能创建不能删除的、有所有权限的用户,这个用户的权限操作怎么能合并入普通角色的处理逻辑中呢?比如现在创建一个用户,我就是直接判断如果他的角色是超级管理员就不允许创建。但是感觉这种方式有点 hard code 的感觉。
    2. 权限的粒度。比如修改自己的密码和修改别人的密码这种请求肯定是不同的权限操作。但是这种权限的判断如果放在业务逻辑代码中是否侵入性会过强?
    6 条回复    2021-09-07 14:08:31 +08:00
    JKeita
        1
    JKeita  
       2021-09-01 15:49:41 +08:00
    控制到对应 url 及请求方式就够了,那种什么修改自己还是修改别人密码的特殊逻辑就放到业务逻辑。
    xuanbg
        2
    xuanbg  
       2021-09-01 20:02:00 +08:00
    不需要存在什么超级管理员,只需要初始化一个用户,一个管理员角色,以及给管理员角色初始化必要的权限并把这个用户添加到角色就行了。
    权限的粒度一般都是一个独立的操作,大部分这种独立操作都能对应到 1 个或多个接口。所以,我可以在网关上面根据 url 来实现鉴权。从而使用户 /角色 /权限能够抽象出来,成为独立于业务存在通用能力。
    seyoatda
        3
    seyoatda  
    OP
       2021-09-02 09:42:55 +08:00
    @xuanbg
    其实就是想内置一个应急使用的 root 用户,但是抛去这点来说其他的用 RBAC 问题都不大。
    @JKeita
    确实是大部分的操作都是可以对应到一个接口的。主要是涉及到权限系统本身的管理就比较复杂。比如角色的添加、用户删除这些的权限处理可能就需要写在业务逻辑里了。
    hsluoyz
        4
    hsluoyz  
       2021-09-03 12:48:31 +08:00
    @seyoatda 你好,我是 Casbin 作者。

    1. 用 ACL with superuser 模型即可: https://casbin.org/docs/en/supported-models
    2. 这种一般是用 ABAC 来解决:判断主体(用户)与客体(密码)的 owner 是不是一致: https://github.com/casbin/casbin/blob/master/examples/abac_model.conf 不过这样密码就是一个实体了,其实比较怪异,可以直接添加一个 set-password API 来设置自己密码,管理员针对其他用户( User )的所有字段具有修改权限。具体怎么设计可以有无数种方式,不同的设计会导致 Casbin 使用上的不同,需要具体问题具体分析。
    seyoatda
        5
    seyoatda  
    OP
       2021-09-06 13:09:19 +08:00
    @hsluoyz 嗯嗯谢谢~。前阵子一直在看 casbin 的文档。感觉自己对权限这块的基础知识还需要加深学习哈哈,在设计和实现上有点踌躇不前。
    Tinywan
        6
    Tinywan  
       2021-09-07 14:08:31 +08:00
    model.conf 直接增加超管的账号就可以啦:

    ```
    [request_definition]
    r = sub, obj, act

    [policy_definition]
    p = sub, obj, act

    [role_definition]
    g = _, _

    [policy_effect]
    e = some(where (p.eft == allow))

    [matchers]
    m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act) || r.sub == 1
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2537 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 15:28 · PVG 23:28 · LAX 07:28 · JFK 10:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.