概述

Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。

Casbin可以

  • 支持自定义请求的格式,默认的请求格式为{subject, object, action}。
  • 具有访问控制模型model和策略policy两个核心概念。
  • 支持RBAC中的多层角色继承,不止主体可以有角色,资源也可以具有角色。
  • 支持内置的超级用户 例如:root或administrator。超级用户可以执行任何操作而无需显式的权限声明。
  • 支持多种内置的操作符,如 keyMatch,方便对路径式的资源进行管理,如 /foo/bar可以映射到/foo*

Casbin不能

  • 身份认证 authentication(即验证用户的用户名、密码),casbin只负责访问控制。应该有其他专门的组件负责身份认证,然后由casbin进行访问控制,二者是相互配合的关系。
  • 管理用户列表或角色列表。 Casbin 认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是 Casbin 的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC方案中用户和角色之间的映射关系。

快速入门

1.安装

1go get github.com/casbin/casbin/v2

2.创建模型文件

model.conf

 1[request_definition]
 2r = sub, obj, act
 3
 4[policy_definition]
 5p = sub, obj, act
 6
 7[role_definition]
 8g = _, _
 9
10[policy_effect]
11e = some(where (p.eft == allow))
12
13[matchers]
14m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

3.创建策略文件

policy.csv

p代表了具体的策略信息,比如alice访问/users的GET访问权限 g代表角色的策略信息,比如alice属于admin组,具有访问/users下的GET和POST权限

1p, alice, /users, GET
2p, bob, /users, POST
3p, admin, /users, GET
4p, admin, /users, POST
5p, admin, /users, DELETE
6g, alice, admin

4.初始化enfocer

 1var (
 2  e   *casbin.Enforcer
 3  err error
 4)
 5
 6func init() {
 7  e, err = casbin.NewEnforcer("model.conf", "policy.csv")
 8  if err != nil {
 9    logrus.Fatal("load file failed, %v", err.Error())
10  }
11}

5.定义一个检测权限的函数

 1func checkPermission(ctx *gin.Context, sub, obj, act string) {
 2  logrus.Infof("sub = %s obj = %s act = %s", sub, obj, act)
 3  ok, err := e.Enforce(sub, obj, act)
 4  if err != nil {
 5    logrus.Print("enforce failed %s", err.Error())
 6    ctx.String(http.StatusInternalServerError, "内部服务器错误")
 7    return
 8  }
 9  if !ok {
10    logrus.Println("权限验证不通过")
11    ctx.String(http.StatusOK, "权限验证不通过")
12    return
13  }
14  logrus.Println("权限验证通过")
15  ctx.String(http.StatusOK, "权限验证通过")
16}

6.定义/users下的2个接口

 1func main() {
 2  r := gin.Default()
 3
 4  r.GET("/users", func(ctx *gin.Context) {
 5    sub := ctx.Query("username")
 6    obj := ctx.Request.URL.Path
 7    act := ctx.Request.Method
 8    checkPermission(ctx, sub, obj, act)
 9  })
10  r.POST("/users", func(ctx *gin.Context) {
11    sub := ctx.Query("username")
12    obj := ctx.Request.URL.Path
13    act := ctx.Request.Method
14    checkPermission(ctx, sub, obj, act)
15  })
16
17  r.Run()
18}

7.运行测试

1go run main.go

请求截图

casbin-rbac

终端输出

casbin-rbac

API操作

这里使用RBAC中的删除用户操作做演示,更多操作请查看文档API概览

创建结构体

1type PermissionObj struct {
2  User string `json:"user" form:"user"`
3  Sub  string `json:"sub" form:"sub"`
4}

增加删除接口

 1  r.DELETE("/users", func(ctx *gin.Context) {
 2    // 先验证用户权限 
 3    var p PermissionObj
 4    ctx.ShouldBind(&p)
 5    obj := ctx.Request.URL.Path
 6    act := ctx.Request.Method
 7    logrus.Infof("sub = %s obj = %s act = %s", p.User, obj, act)
 8    ok, err := e.Enforce(p.User, obj, act)
 9    if err != nil {
10      ctx.String(http.StatusInternalServerError, "内部服务器错误")
11      return
12    }
13    if !ok {
14      ctx.String(http.StatusOK, "您没有权限")
15      return
16    }
17    logrus.Println("权限验证通过")
18    // 删除指定用户
19    ok, err = e.DeleteUser(p.Sub)
20    if err != nil {
21      logrus.Info(err.Error())
22      ctx.String(http.StatusInternalServerError, "内部服务器错误")
23      return
24    }
25    if !ok {
26      ctx.String(http.StatusOK, "删除用户失败")
27      return
28    }
29    ctx.String(http.StatusOK, "删除用户成功")
30    e.SavePolicy()
31  })

运行

1go run main.go

删除用户

casbin-rbac

policy文件

casbin-rbac

看到bob已经从policy文件中删除了。

更多

想了解更多更详细的用法,可以参考casbin官网