with gin
在 Go Gin 中使用 Casbin 实现基于角色的访问控制 (RBAC),需要以下步骤:
步骤 1:初始化 Gin 和 Casbin
引入必要模块
确保引入以下依赖:
- Casbin: 用于权限控制。
- Gorm-Adapter: Casbin 的数据库适配器。
- Gin: Web 框架。
安装依赖:
bash
go get -u github.com/gin-gonic/gin
go get -u github.com/casbin/casbin/v2
go get -u github.com/casbin/gorm-adapter/v3初始化 Casbin 和角色规则
Casbin 模型文件 rbac_model.conf:
ini
[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数据库中的策略可以通过 Gorm-Adapter 进行管理。
步骤 2:编写代码
go
package main
import (
"fmt"
"log"
"net/http"
"github.com/casbin/casbin/v2"
gormadapter "github.com/casbin/gorm-adapter/v3"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func main() {
// 初始化数据库
db, err := gorm.Open(sqlite.Open("gin_casbin.db"), &gorm.Config{})
if err != nil {
log.Fatalf("failed to connect to database: %v", err)
}
// 初始化 Casbin 适配器和 Enforcer
adapter, err := gormadapter.NewAdapterByDB(db)
if err != nil {
log.Fatalf("failed to create adapter: %v", err)
}
enforcer, err := casbin.NewEnforcer("rbac_model.conf", adapter)
enforcer.AddGroupingPolicy("alice", "admin")
enforcer.AddGroupingPolicy("bob", "user")
// 添加权限规则
enforcer.AddPolicy("admin", "/data1", "GET")
enforcer.AddPolicy("user", "/data2", "GET")
if err != nil {
log.Fatalf("failed to create enforcer: %v", err)
}
// 加载策略
if err := enforcer.LoadPolicy(); err != nil {
log.Fatalf("failed to load policy: %v", err)
}
// 初始化 Gin 路由
r := gin.Default()
// 中间件,用于权限验证
r.Use(CasbinMiddleware(enforcer))
// 路由定义
r.GET("/data1", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Access granted to data1!"})
})
r.GET("/data2", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Access granted to data2!"})
})
// 启动服务
if err := r.Run(":8080"); err != nil {
log.Fatalf("failed to start server: %v", err)
}
}
// Casbin 中间件
func CasbinMiddleware(e *casbin.Enforcer) gin.HandlerFunc {
return func(c *gin.Context) {
// 假设从请求头获取用户角色(生产环境应使用更安全的方法)
user := c.GetHeader("X-User")
obj := c.Request.URL.Path
act := c.Request.Method
// 验证权限
ok, err := e.Enforce(user, obj, act)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"})
c.Abort()
return
}
fmt.Println(user, obj, act, ok)
if !ok {
c.JSON(http.StatusForbidden, gin.H{"error": "access denied"})
c.Abort()
return
}
// 权限通过
c.Next()
}
}步骤 3:配置角色和权限
定义角色关系
通过 g 定义用户与角色的关系。例如:
csv
g, alice, admin
g, bob, user定义权限规则
通过 p 定义角色对资源的访问权限。例如:
csv
p, admin, /data1, GET
p, user, /data2, GET添加规则到数据库
可通过代码动态添加:
go
// 添加角色关系
enforcer.AddGroupingPolicy("alice", "admin")
enforcer.AddGroupingPolicy("bob", "user")
// 添加权限规则
enforcer.AddPolicy("admin", "/data1", "GET")
enforcer.AddPolicy("user", "/data2", "GET")
// 保存到数据库
enforcer.SavePolicy()步骤 4:测试
请求示例
假设用户通过 X-User 请求头传递角色信息。
请求
/data1,X-User: alice:httpGET /data1 X-User: alice返回:
json{ "message": "Access granted to data1!" }请求
/data2,X-User: bob:httpGET /data2 X-User: bob返回:
json{ "message": "Access granted to data2!" }请求未授权的资源:
httpGET /data1 X-User: bob返回:
json{ "error": "access denied" }
总结
通过上述代码和配置:
- Casbin 的 RBAC 模型可以灵活管理角色与权限。
- Gin 中的中间件可以确保每次请求根据策略进行验证。
- 策略和角色关系可以存储在数据库中,支持动态调整权限。