跳转至主要内容

Adapters

Casbin 通过 适配器 加载和保存策略。 enforcer 调用 LoadPolicy() 加载规则,在支持时调用 SavePolicy() 持久化规则。适配器放在单独的包中实现,以保持核心库精简。

支持的适配器​

下面按语言列出适配器。要添加第三方适配器,请提交 issue 或 PR。

Adapter Type Author AutoSave Description
File Adapter (built-in) File Casbin ❌ For .CSV (Comma-Separated Values) files
Filtered File Adapter (built-in) File @faceless-saint ❌ For .CSV (Comma-Separated Values) files with policy subset loading support
SQL Adapter SQL @Blank-Xu ✅ MySQL, PostgreSQL, SQL Server, SQLite3 are supported in master branch and Oracle is supported in oracle branch by database/sql
Xorm Adapter ORM Casbin ✅ MySQL, PostgreSQL, TiDB, SQLite, SQL Server, Oracle are supported by Xorm
GORM Adapter ORM Casbin ✅ MySQL, PostgreSQL, Sqlite3, SQL Server are supported by GORM
GORM Adapter Ex ORM Casbin ✅ MySQL, PostgreSQL, Sqlite3, SQL Server are supported by GORM
Ent Adapter ORM Casbin ✅ MySQL, MariaDB, PostgreSQL, SQLite, Gremlin-based graph databases are supported by ent ORM
Beego ORM Adapter ORM Casbin ✅ MySQL, PostgreSQL, Sqlite3 are supported by Beego ORM
SQLX Adapter ORM @memwey ✅ MySQL, PostgreSQL, SQLite, Oracle are supported by SQLX
Sqlx Adapter ORM @Blank-Xu ✅ MySQL, PostgreSQL, SQL Server, SQLite3 are supported in master branch and Oracle is supported in oracle branch by sqlx
GF ORM Adapter ORM @vance-liu ✅ MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
GoFrame ORM Adapter ORM @kotlin2018 ✅ MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
gf-adapter ORM @zcyc ✅ MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
Gdb Adapter ORM @jxo-me ✅ MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
GoFrame V2 Adapter ORM @hailaz ✅ MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
Bun Adapter ORM @JunNishimura ✅ MySQL, SQLite, PostgreSQL, SQL Server are supported by Bun ORM
Filtered PostgreSQL Adapter SQL Casbin ✅ For PostgreSQL
Filtered pgx Adapter SQL @pckhoi ✅ PostgreSQL is supported by pgx
Pgx Adapter SQL @gtoxlili ✅ PostgreSQL is supported by pgx, supports customizable column count
casbin-pgx-adapter SQL @noho-digital ✅ A PostgreSQL adapter for Casbin using the pgx driver.
PostgreSQL Adapter SQL @cychiuae ✅ For PostgreSQL
RQLite Adapter SQL EDOMO Systems ✅ For RQLite
MongoDB Adapter NoSQL Casbin ✅ For MongoDB based on MongoDB Go Driver
RethinkDB Adapter NoSQL @adityapandey9 ✅ For RethinkDB
Cassandra Adapter NoSQL Casbin ❌ For Apache Cassandra DB
DynamoDB Adapter NoSQL HOOQ ❌ For Amazon DynamoDB
Dynacasbin NoSQL NewbMiao ✅ For Amazon DynamoDB
ArangoDB Adapter NoSQL @adamwasila ✅ For ArangoDB
Amazon S3 Adapter Cloud Soluto ❌ For Minio and Amazon S3
Go CDK Adapter Cloud @bartventer ✅ Adapter based on Go Cloud Dev Kit that supports: Amazon DynamoDB, Azure CosmosDB, GCP Firestore, MongoDB, In-Memory
Azure Cosmos DB Adapter Cloud @spacycoder ✅ For Microsoft Azure Cosmos DB
GCP Firestore Adapter Cloud @reedom ❌ For Google Cloud Platform Firestore
GCP Cloud Storage Adapter Cloud qurami ❌ For Google Cloud Platform Cloud Storage
GCP Cloud Spanner Adapter Cloud @flowerinthenight ✅ For Google Cloud Platform Cloud Spanner
Consul Adapter KV store @ankitm123 ❌ For HashiCorp Consul
Redis Adapter (Redigo) KV store Casbin ✅ For Redis
Redis Adapter (go-redis) KV store @mlsen ✅ For Redis
Etcd Adapter KV store @sebastianliu ❌ For etcd
BoltDB Adapter KV store @speza ✅ For Bolt
Bolt Adapter KV store @wirepair ❌ For Bolt
BadgerDB Adapter KV store @inits ✅ For BadgerDB
Protobuf Adapter Stream Casbin ❌ For Google Protocol Buffers
JSON Adapter String Casbin ❌ For JSON
String Adapter String @qiangmzsx ❌ For String
HTTP File Adapter HTTP @h4ckedneko ❌ For http.FileSystem
FileSystem Adapter File @naucon ❌ For fs.FS and embed.FS
NATS JetStream Adapter KV store grepplabs ✅ For NATS JetStream
Kubernetes Adapter Cloud grepplabs ✅ For Kubernetes
备注
  1. 用适配器(显式或隐式)调用 casbin.NewEnforcer() 时,策略会自动加载。
  2. 调用 e.LoadPolicy() 从存储中重新加载策略。
  3. 如果不支持自动保存,修改策略时适配器无法自动持久化改动。需要手动调用 SavePolicy() 持久化所有规则。

示例​

下面是几个适配器的使用示例:

文件适配器(内置)​

用内置的文件适配器初始化 enforcer:

import "github.com/casbin/casbin/v3"

e := casbin.NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")

等价的写法:

import (
"github.com/casbin/casbin/v3"
fileadapter "github.com/casbin/casbin/v3/persist/file-adapter"
)

a := fileadapter.NewAdapter("examples/basic_policy.csv")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

MySQL适配器​

用 127.0.0.1:3306 上的 MySQL 数据库连接初始化 enforcer,用户为 root,无密码:

import (
"github.com/casbin/casbin/v3"
"github.com/casbin/mysql-adapter"
)

a := mysqladapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

使用您自己的存储适配器​

接入自定义适配器:

import (
"github.com/casbin/casbin/v3"
"github.com/your-username/your-repo"
)

a := yourpackage.NewAdapter(params)
e := casbin.NewEnforcer("examples/basic_model.conf", a)

在不同适配器之间迁移/转换​

把策略从适配器 A 迁移到适配器 B:

1.从A加载策略到内存

e, _ := NewEnforcer(m, A)

或者

e.SetAdapter(A)
e.LoadPolicy()

2.从适配器 A 切换到 B

e.SetAdapter(B)

3.将策略从内存保存到B

e.SavePolicy()

运行时加载/保存​

初始化后重新加载模型和策略,或持久化策略改动:

// Reload the model from the model CONF file.
e.LoadModel()

// Reload the policy from file/database.
e.LoadPolicy()

// Save the current policy (usually after changed with Casbin API) back to file/database.
e.SavePolicy()

AutoSave​

支持自动保存的适配器可以把单条策略改动直接写入存储,无需整体保存。这与 SavePolicy() 不同,后者会清空存储并重写所有策略,策略很多时可能带来性能问题。

适配器支持自动保存时,用 Enforcer.EnableAutoSave() 控制这一行为。对兼容的适配器,这个选项默认开启。

备注
  1. 自动保存是可选功能。适配器可以实现,也可以不实现。
  2. 只有 enforcer 的适配器支持时,自动保存才会生效。
  3. 查看上面适配器列表中的 AutoSave 列,确认是否支持。

自动保存的使用示例:

import (
"github.com/casbin/casbin/v3"
"github.com/casbin/xorm-adapter"
_ "github.com/go-sql-driver/mysql"
)

// AutoSave is enabled by default when using compatible adapters with enforcers.
a := xormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

// Disable AutoSave.
e.EnableAutoSave(false)

// Policy changes affect only the in-memory enforcer,
// not the storage.
e.AddPolicy(...)
e.RemovePolicy(...)

// Enable AutoSave.
e.EnableAutoSave(true)

// Policy changes now persist to storage
// in addition to updating the in-memory enforcer.
e.AddPolicy(...)
e.RemovePolicy(...)

更多示例:https://github.com/apache/casbin-xorm-adapter/blob/master/adapter_test.go

如何编写适配器​

实现 Adapter 接口,至少包含两个必需方法:LoadPolicy(model model.Model) error 和 SavePolicy(model model.Model) error。

三个可选方法用于支持自动保存。

方法类型描述
LoadPolicy()必需从存储中加载所有策略规则
SavePolicy()必需将所有策略规则保存到存储中
AddPolicy()可选将策略规则添加到存储中
RemovePolicy()可选从存储中删除策略规则
RemoveFilteredPolicy()可选从存储中删除与过滤器匹配的策略规则
备注

适配器不支持自动保存时,为这三个可选方法提供空实现。 Golang 示例:

// AddPolicy adds a policy rule to the storage.
func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error {
return errors.New("not implemented")
}

// RemovePolicy removes a policy rule from the storage.
func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
return errors.New("not implemented")
}

// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
return errors.New("not implemented")
}

调用这些可选方法时,Casbin enforcer 会忽略 "not implemented" 错误。

适配器的实现要求:

  • 数据结构。至少支持读取六列。
  • 数据库名称。默认为 casbin。
  • 表名。默认为 casbin_rule。
  • Ptype列。命名为 ptype(不是 p_type 或 Ptype)。
  • 表定义:(id int primary key, ptype varchar, v0 varchar, v1 varchar, v2 varchar, v3 varchar, v4 varchar, v5 varchar)。
  • 唯一索引:建在 ptype,v0,v1,v2,v3,v4,v5 列上。
  • LoadFilteredPolicy 接受如下结构的过滤参数:
{
"p": ["", "domain1"],
"g": ["", "", "domain1"]
}

谁负责创建数据库?​

按照惯例,适配器应在 casbin 数据库不存在时自动创建它,并用它存储策略。参考实现:https://github.com/apache/casbin-xorm-adapter

可更新的适配器​

UpdateAdapter 接口扩展了基础的 Adapter 接口,可以直接在存储中更新策略。修改已有规则时,这比先删除再添加更高效。

实现 UpdateAdapter 的适配器提供以下方法:

方法类型描述
UpdatePolicy()可选更新存储中的单条策略规则
UpdatePolicies()可选更新存储中的多条策略规则
UpdateFilteredPolicies()可选更新存储中与过滤条件匹配的策略规则

示例​

可更新适配器的用法:

import (
"github.com/casbin/casbin/v3"
"github.com/casbin/gorm-adapter/v3"
)

a, _ := gormadapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/")
e, _ := casbin.NewEnforcer("examples/rbac_model.conf", a)

// Update a single policy
// Change: p, alice, data1, read -> p, alice, data1, write
e.UpdatePolicy(
[]string{"alice", "data1", "read"},
[]string{"alice", "data1", "write"},
)

// Update multiple policies at once
e.UpdatePolicies(
[][]string{{"alice", "data1", "write"}, {"bob", "data2", "read"}},
[][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}},
)

// Update all policies matching a filter
e.UpdateFilteredPolicies(
[][]string{{"alice", "data1", "write"}},
0,
"alice", "data1", "read",
)

如何编写可更新的适配器​

要实现 UpdateAdapter,在基础的 Adapter 实现上加上更新方法:

// UpdatePolicy updates a policy rule from storage.
// This is part of the UpdateAdapter interface.
func (a *Adapter) UpdatePolicy(sec string, ptype string, oldRule, newRule []string) error {
// Update the policy in storage
// SQL example: UPDATE casbin_rule SET v0=?, v1=?, v2=? WHERE ptype=? AND v0=? AND v1=? AND v2=?
return nil
}

// UpdatePolicies updates multiple policy rules in the storage.
// This is part of the UpdateAdapter interface.
func (a *Adapter) UpdatePolicies(sec string, ptype string, oldRules, newRules [][]string) error {
// Update multiple policies in storage
// Use transactions for consistency
return nil
}

// UpdateFilteredPolicies updates policy rules that match the filter from the storage.
// This is part of the UpdateAdapter interface.
func (a *Adapter) UpdateFilteredPolicies(sec string, ptype string, newRules [][]string, fieldIndex int, fieldValues ...string) error {
// Find policies matching the filter, then update them
return nil
}
备注

不支持 UpdateAdapter 时,Casbin 会自动退回组合使用 RemovePolicy() 和 AddPolicy()。

上下文适配器​

ContextAdapter 为 Casbin 适配器提供感知 context 的操作。

Context 可以为适配器 API 调用提供超时控制等功能。

示例​

gormadapter 支持 context。下面是用 context 做超时控制的示例:

ca, _ := NewContextAdapter("mysql", "root:@tcp(127.0.0.1:3306)/", "casbin")
// Set 300s timeout
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Microsecond)
defer cancel()

err := ca.AddPolicyCtx(ctx, "p", "p", []string{"alice", "data1", "read"})
if err != nil {
panic(err)
}

如何编写一个上下文适配器​

ContextAdapter API 在标准 Adapter API 之上增加了一层 context 处理。实现标准的 Adapter API 后,再用 context 处理包裹你的逻辑。

参考实现:adapter.go

事务​

Casbin 支持事务。 gormadapter 中事务的用法:

db, _ := gorm.Open(...)
adapter, _ := gormadapter.NewTransactionalAdapterByDB(db)
e, _ := casbin.NewTransactionalEnforcer("examples/rbac_model.conf", adapter)

ctx := context.Background()

// WithTransaction executes a function within a transaction.
// Errors trigger rollback; otherwise, automatic commit occurs.
err := e.WithTransaction(ctx, func(tx *casbin.Transaction) error {
tx.AddPolicy("alice", "data1", "read")
tx.AddPolicy("alice", "data1", "write")
return nil
})

// Manual transaction handling
tx, _ := e.BeginTransaction(ctx)
tx.AddPolicy("alice", "data1", "write")
if err := tx.Commit(); err != nil {
// handle transaction failure
}

实现 persist/transaction.go 中的 TransactionalAdapter 和 TransactionContext 即可支持事务。

参考:adapter.go