golang实现ACL/RBAC/ABAC权限控制的授权插件库casbin的使用

Golang实现ACL/RBAC/ABAC权限控制的授权插件库Casbin的使用

Casbin是一个强大高效的Golang开源访问控制库,支持多种访问控制模型,包括ACL、RBAC和ABAC等。

安装

go get github.com/casbin/casbin/v2

基本使用

1. 创建Enforcer

首先需要创建一个Casbin执行器(Enforcer),需要指定模型文件和策略文件:

e, _ := casbin.NewEnforcer("path/to/model.conf", "path/to/policy.csv")

2. 权限检查

在需要权限检查的地方调用Enforce方法:

sub := "alice" // 用户
obj := "data1" // 资源
act := "read"  // 操作

if res, _ := e.Enforce(sub, obj, act); res {
    // 允许alice读取data1
} else {
    // 拒绝请求,显示错误
}

模型文件示例

ACL模型

basic_model.conf:

# Request定义
[request_definition]
r = sub, obj, act

# Policy定义
[policy_definition]
p = sub, obj, act

# Policy效果
[policy_effect]
e = some(where (p.eft == allow))

# 匹配器
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

RBAC模型

rbac_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) && r.obj == p.obj && r.act == p.act

ABAC模型

abac_model.conf:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub_rule, obj, act

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

[matchers]
m = eval(p.sub_rule) && r.obj == p.obj && r.act == p.act

策略文件示例

ACL策略

basic_policy.csv:

p, alice, data1, read
p, bob, data2, write

RBAC策略

rbac_policy.csv:

p, admin, data1, read
p, admin, data1, write
p, user, data1, read
g, alice, admin
g, bob, user

完整示例

下面是一个完整的RBAC实现示例:

package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
)

func main() {
	// 1. 创建Enforcer
	e, err := casbin.NewEnforcer("rbac_model.conf", "rbac_policy.csv")
	if err != nil {
		fmt.Println("创建Enforcer失败:", err)
		return
	}

	// 2. 检查权限
	checkPermission(e, "alice", "data1", "read")   // 应该允许
	checkPermission(e, "alice", "data1", "write")  // 应该允许
	checkPermission(e, "bob", "data1", "read")     // 应该允许
	checkPermission(e, "bob", "data1", "write")    // 应该拒绝
	checkPermission(e, "bob", "data2", "read")     // 应该拒绝(没有定义data2的策略)
}

func checkPermission(e *casbin.Enforcer, sub, obj, act string) {
	ok, _ := e.Enforce(sub, obj, act)
	if ok {
		fmt.Printf("%s 被允许 %s %s\n", sub, act, obj)
	} else {
		fmt.Printf("%s 被拒绝 %s %s\n", sub, act, obj)
	}
}

高级功能

1. 动态策略管理

Casbin提供了API来动态管理策略:

// 添加策略
e.AddPolicy("alice", "data1", "read")

// 删除策略
e.RemovePolicy("alice", "data1", "read")

// 获取用户的所有角色
roles, _ := e.GetImplicitRolesForUser("alice")

2. 多种存储适配器

Casbin支持多种存储适配器,可以将策略存储在数据库、Redis等:

// 使用Gorm适配器
a, _ := gormadapter.NewAdapter("mysql", "mysql_connection_string")
e, _ := casbin.NewEnforcer("model.conf", a)

3. ABAC属性访问控制

ABAC允许基于属性进行访问控制:

type User struct {
	Name string
	Age  int
}

user := User{Name: "alice", Age: 18}
ok, _ := e.Enforce(user, "data1", "read")

对应的模型文件需要支持ABAC规则。

总结

Casbin是一个功能强大且灵活的访问控制库,支持多种访问控制模型,可以轻松集成到Golang项目中。通过定义模型文件和策略文件,可以实现复杂的权限控制逻辑。


更多关于golang实现ACL/RBAC/ABAC权限控制的授权插件库casbin的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现ACL/RBAC/ABAC权限控制的授权插件库casbin的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang权限控制库Casbin使用指南

Casbin是一个强大的、高效的、开源的访问控制库,支持ACL、RBAC、ABAC等多种权限模型。下面我将详细介绍如何在Golang中使用Casbin实现权限控制。

安装Casbin

首先安装Casbin核心库和Golang适配器:

go get github.com/casbin/casbin/v2

基本概念

Casbin的核心是PERM元模型,包含:

  • Policy:定义访问控制策略
  • Model:定义访问控制模型
  • Enforcer:执行访问控制的组件

ACL (访问控制列表) 实现

1. 创建模型文件 model.conf

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

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

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

2. 创建策略文件 policy.csv

p, alice, data1, read
p, bob, data2, write

3. Golang代码实现

package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
)

func main() {
	// 创建enforcer,传入模型文件和策略文件
	e, err := casbin.NewEnforcer("model.conf", "policy.csv")
	if err != nil {
		panic(err)
	}

	// 检查权限
	checkPermission(e, "alice", "data1", "read")   // true
	checkPermission(e, "bob", "data1", "read")     // false
	checkPermission(e, "bob", "data2", "write")    // true
	checkPermission(e, "alice", "data2", "write")   // false
}

func checkPermission(e *casbin.Enforcer, sub, obj, act string) {
	ok, _ := e.Enforce(sub, obj, act)
	if ok {
		fmt.Printf("%s can %s %s\n", sub, act, obj)
	} else {
		fmt.Printf("%s cannot %s %s\n", sub, act, obj)
	}
}

RBAC (基于角色的访问控制) 实现

1. 修改模型文件 rbac_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) && r.obj == p.obj && r.act == p.act

2. 修改策略文件 rbac_policy.csv

p, admin, data1, read
p, admin, data1, write
p, user, data1, read

g, alice, admin
g, bob, user

3. Golang代码实现

package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
)

func main() {
	e, err := casbin.NewEnforcer("rbac_model.conf", "rbac_policy.csv")
	if err != nil {
		panic(err)
	}

	// 检查权限
	checkPermission(e, "alice", "data1", "read")   // true (admin)
	checkPermission(e, "alice", "data1", "write")  // true (admin)
	checkPermission(e, "bob", "data1", "read")     // true (user)
	checkPermission(e, "bob", "data1", "write")    // false
}

func checkPermission(e *casbin.Enforcer, sub, obj, act string) {
	ok, _ := e.Enforce(sub, obj, act)
	if ok {
		fmt.Printf("%s can %s %s\n", sub, act, obj)
	} else {
		fmt.Printf("%s cannot %s %s\n", sub, act, obj)
	}
}

ABAC (基于属性的访问控制) 实现

ABAC不需要策略文件,而是通过属性进行判断。

1. 创建模型文件 abac_model.conf

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub_rule, obj, act

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

[matchers]
m = eval(p.sub_rule) && r.obj == p.obj && r.act == p.act

2. Golang代码实现

package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
)

type User struct {
	Name string
	Age  int
}

func main() {
	e, err := casbin.NewEnforcer("abac_model.conf")
	if err != nil {
		panic(err)
	}

	// 添加策略
	e.AddPolicy(`r.sub.Age > 18`, "data1", "read")
	e.AddPolicy(`r.sub.Name == "alice"`, "data2", "write")

	// 检查权限
	alice := User{Name: "alice", Age: 20}
	bob := User{Name: "bob", Age: 16}

	checkPermission(e, alice, "data1", "read")  // true (age > 18)
	checkPermission(e, bob, "data1", "read")    // false
	checkPermission(e, alice, "data2", "write") // true (name == alice)
	checkPermission(e, bob, "data2", "write")   // false
}

func checkPermission(e *casbin.Enforcer, sub interface{}, obj, act string) {
	ok, _ := e.Enforce(sub, obj, act)
	if ok {
		fmt.Printf("%v can %s %s\n", sub, act, obj)
	} else {
		fmt.Printf("%v cannot %s %s\n", sub, act, obj)
	}
}

实际应用集成

在实际Web应用中,可以结合中间件使用:

package main

import (
	"github.com/casbin/casbin/v2"
	"github.com/gin-gonic/gin"
)

func main() {
	e, err := casbin.NewEnforcer("rbac_model.conf", "rbac_policy.csv")
	if err != nil {
		panic(err)
	}

	r := gin.Default()

	// 使用Casbin中间件
	r.Use(func(c *gin.Context) {
		user := c.GetHeader("X-User")
		path := c.Request.URL.Path
		method := c.Request.Method

		ok, err := e.Enforce(user, path, method)
		if err != nil || !ok {
			c.AbortWithStatusJSON(403, gin.H{"error": "forbidden"})
			return
		}
		c.Next()
	})

	r.GET("/data1", func(c *gin.Context) {
		c.JSON(200, gin.H{"message": "access granted to data1"})
	})

	r.POST("/data1", func(c *gin.Context) {
		c.JSON(200, gin.H{"message": "write access granted to data1"})
	})

	r.Run(":8080")
}

高级功能

  1. 策略持久化:可以使用数据库适配器存储策略

    // 使用Gorm适配器
    a, _ := gormadapter.NewAdapter("mysql", "mysql_conn_string")
    e, _ := casbin.NewEnforcer("model.conf", a)
    
  2. 自动加载策略:当策略变更时自动重新加载

    e.StartAutoLoadPolicy(5 * time.Second)
    
  3. 批量权限检查:使用BatchEnforce检查多个权限

    requests := [][]interface{}{
        {"alice", "data1", "read"},
        {"bob", "data2", "write"},
    }
    results, _ := e.BatchEnforce(requests)
    

Casbin提供了强大而灵活的权限控制能力,可以根据项目需求选择合适的模型或组合多种模型。以上示例展示了基本用法,实际应用中可能需要根据业务需求进行调整。

回到顶部