golang gin 基于 Casbin 实现权限控制

文章目录

    最近在使用 golang gin 开发一套公司内部的人事管理系统,但是发现权限管理比之前搞的系统要复杂不少,
    所以我想借机了解一下传说中的 Casbin 权限控制库,看看是否可以借鉴一下。

    涉及权限控制的需求场景

    • 人事部门负责人需要能看到所有的人事数据
    • 人事部门的普通 HR,只能看到部分部门的人事数据。即只能看到自己负责的部门数据
    • IT 部门或者行政部门指定人员,能看到资产管理模块的数据。即每个员工有哪些名下资产,显示器,主机,桌子椅子之类的。方便离职时进行资产回收。
    • 部门负责人能看到自己部门的所有员工数据,除了薪资相关的字段。且只有看的权限。不能修改和删除。
    • 员工个人能通过企业微信的授权登录,查看自己的个人信息。包括姓名,工号,入职时间,部门,岗位等。能修改一些基础信息等。
    • 一个集团公司下,有多个子公司。每个子公司都有自己的 HR 系统。HR 系统的权限控制需要支持集团公司下的多租户模式。

    现有 gin route group 的缺陷

    总感觉,我目前实用的 gin route group + middleware 的方式,无法满足复杂的权限控制需求。
    而且对于粒度更细的权限控制,无法做到灵活的配置。

    我目前实现的系统,都是基于角色的权限控制。即每个角色对应一组权限。
    还是不太灵活。

    当然根源是,gin 没有内置权限控制的功能,我自己实现的这套感觉很乱。我不知道规范的做法是怎样的。
    所以,需要找个开源的权限控制库,学习参考一下。

    Casbin 示例

    policy.csv 文件内容

    p, alice, /api/*, read
    p, bob, /version, write
    

    预定义一些策略,也可以存储到数据库, alice 可以访问所有 /api 开头的路径,bob 只能访问 /version 路径。

    go 代码

    // 加载模型与策略,也可以存储到数据库
    e, err := casbin.NewEnforcer("path/to/model.conf", "path/to/policy.csv")
    
    sub := "alice" // the user that wants to access a resource.
    obj := "data1" // the resource that is going to be accessed.
    act := "read" // the operation that the user performs on the resource.
    
    ok, err := e.Enforce(sub, obj, act) //判断用户是否有权限
    

    实际使用中,e.Enforce() 方法通常会在中间件 (middleware) 中调用,以便在处理请求之前进行权限检查。

    参考:

    https://juejin.cn/post/7108533587292454949

    Casbin 的功能简介

    一种基于元模型的访问控制策略描述语言 PML (PERM modeling language) 及其实施机制 PML-EM (PML enforcement mechanism)

    • 策略语言无关性
    • 访问控制模型无关性: 即支持多种访问控制模型,如基于角色的访问控制(RBAC)、基于属性的访问控制(ABAC)以及 BLP 模型等。
    • 程序设计语言无关性

    参考论文:

    https://www.jos.org.cn/jos/article/pdf/5624

    一些术语

    • 访问控制模型(Access Control Model):定义了如何对资源进行访问控制的规则和方法。
    • 访问控制策略(Access Control Policy):具体的规则和策略,用于定义哪些用户或角色可以访问哪些资源以及可以执行哪些操作。
    • 访问控制列表(Access Control List, ACL):一种常见的访问控制策略,列出了每个用户或角色对特定资源的访问权限。
    • 角色(Role):一组权限的集合,用户可以被分配到一个或多个角色中,以简化权限管理。
    • 权限(Permission):对资源的具体操作权限,如读取、写入、删除等。
    • 策略(Policy):定义了访问控制的规则,通常包括主体(用户或角色)、客体(资源)和操作(权限)。
    • 策略引擎(Policy Engine):用于评估访问控制策略并决定是否允许访问的组件。
    • 策略存储(Policy Store):存储访问控制策略的地方,可以是文件、数据库或其他存储系统。
    • 基于属性访问控制 (attribute-based access control, 简称 ABAC) 模型
    • 基于角色访问控制 (role-based access control, 简称 RBAC) 模型
    • PERM (Policy, Effect, Request, Matchers) 模型
    • 策略描述语言 PML (PERM modeling language)
    • 基于请求(request)、策略(policy)、匹配器(matcher)、策略效果(effect) 的访问控制元模型 PERM (policy-effect-request-matcher)
    • 策略实施机制 PML-EM (PML enforcement mechanism)
    • 认证(Authentication): 在 Web 程序中对应的是 HTTP Status 401 错误
    • 授权(Authorization): 在 Web 程序中对应的是 HTTP Status 403 错误

    Casbin 入门介绍

    https://casbin.org/docs/tutorials/

    里面有一堆高质量的介绍文档,找几篇读读,就能有个大概的了解。剩下的就是动手测试一下了。

    Request 原语

    一个访问请求通常由经典的三元组构成:

    • Subject:请求的主体,通常是用户或角色。
    • Object:请求的对象,通常是资源或数据。
    • Action:请求的操作,通常是对资源的具体操作,如读取、写入等。

    Policy 原语 (策略规则) 类似,也是这三个部分。

    ACL (Access Control List) 与 RBAC (Role-Based Access Control),ABAC (Attribute-Based Access Control) 的区别

    • ACL 需要存储每个用户对每个资源的权限,适用于用户数量较少的场景。
    • RBAC 通过角色来管理权限,适用于用户数量较多的场景。用户可以被分配到一个或多个角色中,角色定义了一组权限。但是,不能做的很细粒度的控制。这也是我目前遇到的困扰。但是我感觉,就算在代码中写死部分细微的权限控制逻辑,也能满足需求。唯一的问题就是对于管理员来说不可见,也不能灵活配置。例如,同样是人事部门的角色,有的 HR 能修改一些基础信息等,有的 HR 只能查看数据。
    • ABAC 通过属性来管理权限,适用于需要更细粒度控制的场景。用户、资源和环境的属性可以用来定义访问控制策略。

    参考:

    https://github.com/xizhibei/blog/issues/101

    多租户的支持

    参考:

    https://www.cnblogs.com/wang_yb/p/9987397.html

    策略规则 Policy 存储到数据库的方法

    保存到 CSV 不是一个好的选择,应该存储到数据库中。这样可以更灵活地管理和查询策略规则。

    否则,每次都需要登录服务器,修改 CSV 文件,然后重启服务,才能生效。这样不够灵活。

    参考:

    https://casbin.org/zh/docs/policy-storage/

    这里支持 Gorm MySQL 的适配器:

    https://casbin.org/zh/docs/adapters

    实际场景实用

    https://www.cnblogs.com/studyzy/p/11380736.html

    gin middleware 插件

    https://casbin.org/zh/docs/middlewares

    这里推荐了两个插件 authz (这个居然是 gin 官方的,不可思议) 和 go-casbin, 不过这么简单的 middleware,我感觉并不需要三方的实现。
    不过可以参考一下代码。

    感想

    • 涉及的概念比较多,需要耐心学习和理解,即便拿出半天时间来阅读理解,都是值得的。
    • 即便最后不使用 Casbin 作为权限控制的实现,也能从中学到很多关于权限控制的设计思路和实现方式。
    • 是否有简化版的 casbin 实现,只保留策略规则的部分。

    今天就到这里吧,实在看不下去了,太枯燥了。

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式