# 6.5 Casbin

# 6.5.1 第三方库

# 6.5.2 配置参数

名称 类型 描述
dsn string 连接串
table string 存储权限的表名称
model string 模型配置文件路径

# 6.5.3 示例代码

以下完整示例详见:third-casbin-example (opens new window)

  1. 组件封装

文件位置:third-casbin-example/casbin/casbin.go (opens new window)

package casbin

import (
	"fmt"
	"log"

	"github.com/dobyte/due/v2/core/pool"
	"github.com/dobyte/due/v2/etc"
	casbin "github.com/dobyte/gorm-casbin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var factory = pool.NewFactory(func(name string) (*Enforcer, error) {
	return NewInstance(fmt.Sprintf("etc.casbin.%s", name))
})

type Enforcer = casbin.Enforcer

type Config struct {
	DSN   string `json:"dsn"`
	Table string `json:"table"`
	Model string `json:"model"`
}

// Instance 获取实例
func Instance(name ...string) *Enforcer {
	var (
		err error
		ins *Enforcer
	)

	if len(name) == 0 {
		ins, err = factory.Get("default")
	} else {
		ins, err = factory.Get(name[0])
	}

	if err != nil {
		log.Fatalf("create casbin instance failed: %v", err)
	}

	return ins
}

// NewInstance 新建实例
func NewInstance[T string | Config | *Config](config T) (*Enforcer, error) {
	var (
		conf *Config
		v    any = config
	)

	switch c := v.(type) {
	case string:
		conf = &Config{
			DSN:   etc.Get(fmt.Sprintf("%s.dsn", c)).String(),
			Table: etc.Get(fmt.Sprintf("%s.table", c)).String(),
			Model: etc.Get(fmt.Sprintf("%s.model", c)).String(),
		}
	case Config:
		conf = &c
	case *Config:
		conf = c
	}

	db, err := gorm.Open(mysql.New(mysql.Config{
		DSN: conf.DSN,
	}))
	if err != nil {
		return nil, err
	}

	return casbin.NewEnforcer(&casbin.Options{
		Model:    conf.Model,
		Enable:   true,
		Autoload: true,
		Table:    conf.Table,
		Database: db,
	})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  1. 配置示例

文件位置:third-gorm-example/etc/etc.toml (opens new window)

[casbin.default]
    # dsn连接信息
	dsn = "root:123456@tcp(127.0.0.1:3306)/due_admin?charset=utf8mb4&parseTime=True&loc=Local"
    # casbin策略表
	table = "casbin_policy"
	# casbin权限模型
	model = "./resource/model.conf"
1
2
3
4
5
6
7
  1. 模型配置

文件位置:third-casbin-example/resource/model.conf (opens new window)

[request_definition]
r = sub, obj

[policy_definition]
p = sub, obj

[role_definition]
g = _, _

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

[matchers]
m = g(r.sub, p.sub) == true && keyMatch2(r.obj, p.obj) == true || r.sub == "1"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 组件调用

文件位置:third-casbin-example/main.go (opens new window)

package main

import (
	casbincomp "third-casbin-example/casbin"

	"github.com/dobyte/due/v2/log"
)

func main() {
	enforcer := casbincomp.Instance("default")

	// add a permission node for role
	ok, err := enforcer.AddPolicy("role_1", "node_1")
	if err != nil {
		log.Fatalf("Add policy exception:%s \n", err.Error())
	}

	if ok {
		log.Info("Add policy successful")
	} else {
		log.Info("Add policy failure")
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23