go-admin后台设计之casbin权限管理
发布日期:2021-05-27 01:30:22 浏览次数:29 分类:精选文章

本文共 4351 字,大约阅读时间需要 14 分钟。

Casbin权限管理库深度探索

1. 概要

权限管理是每个系统或服务都会直接或间接涉及的部分。权限管理确保了资源(大部分时候是数据)的安全。由于权限管理通常与业务高度关联,每当业务发生变化时,权限调整往往需要投入大量精力。然而,权限的本质并没有那么复杂,它主要是对访问的控制。使用一套完善的访问控制接口,再加上简单的权限模型,就可以处理复杂的访问控制场景。

2. PERM模型

PERM(Policy, Effect, Request, Matcher)模型简单却反映了权限管理的本质——访问控制。以下是PERM模型的四个核心概念:

  • Policy(策略):定义权限规则。
  • Effect(效果):多个Policy组合后决定的结果(allow或deny)。
  • Request(请求):表示访问请求,包括操作者(Subject)、操作对象(Object)和操作方法(Action)。
  • Matcher(匹配器):判断Request是否符合Policy规则。

PERM模型示意图


3. Casbin权限库

Casbin是一个基于Go语言构建的轻量级开源访问控制框架([GitHub开源](https://github.com/hsluoyz/casbin))。它采用元模型设计理念,支持多种经典的访问控制方案,例如基于角色的访问控制(RBAC)和基于属性的访问控制(ABAC)。

Casbin的主要特性

  • 可定制请求格式:默认请求格式为{subject,object,action}
  • 核心概念
    • Model(模型)Policy(策略):是访问控制的两个核心概念。
  • 支持多层角色的RBAC:主体和资源可以有多个角色。
  • 超级用户支持:如root或Administrator,可无需授权策略访问任意资源。
  • 路径式资源管理:支持操作符如keyMatch,便于管理复杂的资源路径(如 /foo/bar 可以映射到 /foo/*)。
  • Casbin不做的事情

  • 身份认证:Casbin不负责验证用户身份。身份认证应由专门的组件完成,Casbin仅负责访问控制。
  • 用户和角色的管理:Casbin假设所有策略和请求中提到的用户、角色和资源都是有效的。用户和角色管理应由应用程序完成。

  • 4. 核心概念

    Modelfile定义

    Modelfile用于定义权限模型,Casbin支持多种常见场景,如:

    • ACL(Access Control List)
    • ACL with Super User
    • RBAC(基于角色的访问控制)
    • ABAC(基于属性的访问控制)

    Modelfile定义语法

    Casbin基于PERM模型,modelfile中主要定义以下部分:

  • Request Definition

    [request_definition]r = sub, obj, act

    分别表示访问请求中的Subject(操作者)、Object(操作对象)和Action(操作方法)。

  • Policy Definition

    [policy_definition]p = sub, obj, actp2 = sub, act

    每一条规则称为policy rule,p2定义的是对所有sub的资源都允许执行act的操作。

  • Policy Effect

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

    表示只要有任意一条policy rule允许,结果为allow。

  • Matchers

    [matchers]m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

    定义请求与policy rule的匹配规则,决定最终的allow或deny结果。

  • Role Definition

    [role_definition]g = _, _ g2 = _, _g3 = _, _, _

    g、g2、g3表示不同类型的RBAC体系。,表示用户和角色,,,_表示用户、角色和域(租户)。


  • 5. Policyfile定义

    Policyfile定义具体的策略。权限检查基于定义的modelfile和policyfile完成。相较于modelfile,policyfile中的内容更具体。

    Modelfile示例

    [request_definition]r = sub, obj, act[policy_definition]p = sub, obj, actp2 = sub, act[policy_effect]e = some(where(p.efect == allow))[matchers]m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act[role_definition]g = _, _

    Policyfile示例

    p, superAdmin, project, readp, superAdmin, project, writep, admin, project, readp, admin, project, writep, admin, asse, readp, admin, asse, writep, zhuangjia, project, writep, zhuangjia, asse, writeg, quyuan, adming, wenyin, zhuangjia

    6. 使用示例

    简单的RBAC示例

    // demo1.gopackage mainimport (	"fmt"	"log"	"github.com/casbin/casbin")
    func TestRBAC() {	e := casbin.NewEnforcer("demo1.conf", "demo1.csv")	fmt.Printf("RBAC test start")	// superAdmin	if e.Enforce("superAdmin", "project", "read") {		log.Println("superAdmin can read project")	} else {		log.Fatal("ERROR: superAdmin can not read project")	}	// salty testing	if e.Enforce("wenyin", "project", "read") {		log.Fatal("ERROR: wenyin can read project")	} else {		log.Println("wenyin can not read project")	}	// ...其他测试逻辑}

    多租户示例

    // demo2.gopackage mainimport (	"fmt"	"log"	"github.com/casbin/casbin")
    func TestTenants() {	e := casbin.NewEnforcer("demo2.conf", "demo2.csv")	fmt.Printf("RBAC TENANTS test start")	// superAdmin	if e.Enforce("superAdmin", "gy", "project", "read") {		log.Println("superAdmin can read project in gy")	} else {		log.Fatal("ERROR: superAdmin can not read project in gy")	}	// ...其他测试逻辑}

    7. Gin+GORM+Casbin示例

    以下是一个使用Gin框架、GORM数据库和Casbin权限库的示例:

    // casbin-gin-gorm.gopackage mainimport (	"fmt"	"github.com/casbin/casbin"	gormadapter "github.com/casbin/gorm-adapter"	"github.com/gin-gonic/gin"	_ "github.com/go-sql-driver/mysql")func main() {	a := gormadapter.NewAdapter("mysql", "root:123456@tcp(127.0.0.1:3306)/gorm1", true)	e := casbin.NewEnforcer("casbin.conf", a)	e.AddPolicy("admin", "/api/v1/aa", "GET")	e.LoadPolicy()	r := gin.New()	r.Use(AuthRoleHandler(e))	r.GET("/api/v1/aa", func(c *gin.Context) {		fmt.Println("Hello 接收到/api/v1/aa GET请求..")		c.String(200, "已授权")	})	r.GET("/api/v1/bb", func(c *gin.Context) {		fmt.Println("Hello 接收到/api/v1/bb 到GET请求..")		c.String(200, "已授权")	})	r.Run(":8080") // 默认监听8080端口}// 拦截器func AuthRoleHandler(e *casbin.Enforcer) gin.HandlerFunc {	return func(c *gin.Context) {		// 获取请求的URI		obj := c.Request.URL.RequestURI()		// 获取请求方法		act := c.Request.Method		// 获取用户角色		sub := "admin"		if e.Enforce(sub, obj, act) {			fmt.Println("通过权限")			c.Next()		} else {			fmt.Println("权限没有通过")			c.String(200, "没有权限")			c.Abort()		}	}}

    总结

    Casbin权限管理库功能强大且易于使用,但其实现则不简单。通过合理定义modelfile和policyfile,可以将具体业务中的权限要求映射到Casbin中,借助其API快速实现权限管理。更多使用示例可以参考go-admin

    上一篇:随笔:进程间描述字fd的传递
    下一篇:徒手调优实现一个支持百万级并发服务器

    发表评论

    最新留言

    网站不错 人气很旺了 加油
    [***.192.178.218]2025年04月28日 19时19分37秒