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
更多关于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")
}
高级功能
-
策略持久化:可以使用数据库适配器存储策略
// 使用Gorm适配器 a, _ := gormadapter.NewAdapter("mysql", "mysql_conn_string") e, _ := casbin.NewEnforcer("model.conf", a)
-
自动加载策略:当策略变更时自动重新加载
e.StartAutoLoadPolicy(5 * time.Second)
-
批量权限检查:使用BatchEnforce检查多个权限
requests := [][]interface{}{ {"alice", "data1", "read"}, {"bob", "data2", "write"}, } results, _ := e.BatchEnforce(requests)
Casbin提供了强大而灵活的权限控制能力,可以根据项目需求选择合适的模型或组合多种模型。以上示例展示了基本用法,实际应用中可能需要根据业务需求进行调整。