一、Casbin 简介
Casbin 是一个强大的、高效的开源访问控制框架,支持多种访问控制模型(ACL、RBAC、ABAC 等),主要用于对用户的权限进行动态管理。Casbin 提供了一种灵活的权限管理方式,开发者可以根据实际需求,自定义访问控制策略。
• 主要特点:
• 支持多种访问控制模型(ACL、RBAC、ABAC)。
• 通过策略文件灵活管理权限规则。
• 支持多种存储后端(如内存、文件、数据库等)。
• 支持权限管理的实时更新。
二、Casbin 的基本概念
在 Casbin 中,权限控制由三部分组成:
-
模型(Model): 定义了权限控制的逻辑规则。
-
策略(Policy): 定义了权限数据,如谁可以访问什么资源、做什么操作。
-
请求(Request): 用户的访问请求,用于验证权限。
Casbin 的模型文件通常是一个 .conf 文件,定义了访问控制逻辑,主要包含以下部分:
• 请求定义([request_definition]): 定义访问请求的结构(如用户、资源、操作)。
• 策略定义([policy_definition]): 定义权限策略的结构。
• 角色定义([role_definition]): 定义角色继承关系,用于 RBAC。
• 策略效果([policy_effect]): 定义多条策略规则的效果(如允许/拒绝)。
• 匹配器([matchers]): 定义请求和策略的匹配规则。
三.实践
package casbin
import (
"context"
"github.com/casbin/casbin/v2"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/kitex/pkg/klog"
"github.com/czczcz831/tiktok-mall/app/api/conf"
"github.com/czczcz831/tiktok-mall/app/user/biz/dal/mysql"
"github.com/czczcz831/tiktok-mall/common/utils"
gormadapter "github.com/casbin/gorm-adapter/v3"
casbinHertz "github.com/hertz-contrib/casbin"
)
var (
CasbinEnforcer *casbin.Enforcer
CasbinHertzMiddleware *casbinHertz.Middleware
)
const (
ADMIN_ROLE = "Admin"
CUSTOMER_ROLE = "Customer"
SELLER_ROLE = "Seller"
)
const (
CUSTOMER_OBJECT = "customer_obj"
SELLER_OBJECT = "seller_obj"
)
func SubjectFromToken(ctx context.Context, c *app.RequestContext) string {
token := c.GetRequest().Header.Get("Authorization")
if token == "" {
return ""
}
publicKeyHexString := conf.GetConf().JWT.PublicSecret
uuid, _, err := utils.VerifyToken(token, publicKeyHexString)
if err != nil {
return ""
}
return uuid
}
func Init() {
a, err := gormadapter.NewAdapterByDB(mysql.DB)
if err != nil {
klog.Fatalf("new casbin enforcer failed: %v", err)
}
CasbinEnforcer, err = casbin.NewEnforcer("casbin.conf", a)
if err != nil {
klog.Fatalf("new casbin enforcer failed: %v", err)
}
CasbinEnforcer.EnableAutoSave(true)
err = CasbinEnforcer.LoadPolicy()
if err != nil {
klog.Fatalf("load policy failed: %v", err)
}
//初始化
//AdminRole
CasbinEnforcer.AddPolicy(ADMIN_ROLE, "*", "*")
//CustomerRole
CasbinEnforcer.AddPolicy(CUSTOMER_ROLE, CUSTOMER_OBJECT, "*")
//SellerRole
CasbinEnforcer.AddPolicy(SELLER_ROLE, SELLER_OBJECT, "*")
CasbinEnforcer.AddPolicy(SELLER_ROLE, CUSTOMER_OBJECT, "*")
//Superuser
CasbinEnforcer.AddRoleForUser("superuser-uuid", ADMIN_ROLE)
CasbinEnforcer.SavePolicy()
if err != nil {
klog.Fatalf("load policy failed: %v", err)
}
CasbinHertzMiddleware, err = casbinHertz.NewCasbinMiddlewareFromEnforcer(CasbinEnforcer, SubjectFromToken)
if err != nil {
klog.Fatalf("new casbin middleware failed: %v", err)
}
}
在我们的电商系统中,不同角色的用户需要拥有不同的权限,比如管理员可以访问所有资源,客户只能查看自己的信息,卖家则可以管理店铺以及和客户进行互动。为了实现这些需求,我使用了 Casbin,一个灵活的权限管理框架,它支持基于角色的访问控制(RBAC),并且可以通过数据库存储策略,方便动态管理。
代码的核心逻辑主要分为几个部分。首先是初始化 Casbin 的逻辑。在 Init 函数中,我通过 gormadapter.NewAdapterByDB 将 MySQL 数据库作为策略存储后端,并加载了一个 Casbin 的模型配置文件(casbin.conf)。这一步非常重要,因为 Casbin 需要知道如何匹配请求和策略,以及如何定义角色和权限关系。模型文件中包含了基础的权限匹配规则,比如用户、资源和操作的结构。
初始化后,我定义了几种角色及其对应的权限。我们有三个主要角色:管理员(Admin)、客户(Customer)和卖家(Seller)。通过 AddPolicy 方法,我分别为这三个角色赋予了不同的权限。例如,管理员可以访问所有资源(* 表示通配符),客户只能访问客户相关的资源,卖家既可以访问卖家资源,也可以与客户资源进行交互。
此外,我还为一个超级用户指定了管理员角色。这里使用了 AddRoleForUser 方法,通过用户的 UUID 来绑定角色,这样超级用户就可以拥有管理员的权限。我们还开启了 EnableAutoSave 功能,这样每次对策略的更改都会自动保存到数据库,避免忘记保存带来的问题。
在权限验证的过程中,我们需要从用户的请求中提取身份信息。为此,我实现了 SubjectFromToken 方法,它从请求头中获取 Authorization Token,并通过 JWT 解密来提取用户的 UUID。这个 UUID 就是权限校验时的主体(sub)。
为了让 Casbin 和我们的 Web 框架 Hertz 集成,我通过 casbinHertz.NewCasbinMiddlewareFromEnforcer 方法初始化了一个 Casbin 中间件,并将上面提取用户身份的逻辑绑定到中间件中。这个中间件会在每次请求时拦截并验证权限,确保用户只能访问他们被授权的资源。
整体上,这套权限管理方案清晰而灵活。Casbin 的核心在于模型和策略的分离,通过动态地加载和更新策略,我们可以轻松地适应业务需求的变化,比如为新角色赋予权限或者调整现有角色的权限。而通过数据库持久化存储策略,也避免了重启服务时权限数据丢失的问题。
总结来说,Casbin 为我们的电商系统提供了一个强大的权限管理工具,它不仅实现了 RBAC 的基础功能,还通过与 JWT 和 Hertz 的集成,使整个权限校验过程高效、透明。对开发者来说,只需要关注模型配置和策略定义,复杂的权限验证工作都交给了 Casbin 和中间件来处理,非常省心。