跳转至主要内容

Adapters

在Casbin中,策略存储是作为一个适配器(也称为Casbin的中间件)来实现的。 Casbin用户可以使用适配器从存储中加载策略规则(也称为LoadPolicy()),或者将策略规则保存到存储中(也称为SavePolicy())。 为了保持轻量级,我们没有将适配器代码放在主库中。

支持的适配器

下面提供了Casbin适配器的完整列表。 欢迎任何第三方对新适配器的贡献,请通知我们,我们会将其放入此列表:

AdapterTypeAuthorAutoSaveDescription
File Adapter (built-in)FileCasbinFor .CSV (Comma-Separated Values) files
Filtered File Adapter (built-in)File@faceless-saintFor .CSV (Comma-Separated Values) files with policy subset loading support
SQL AdapterSQL@Blank-XuMySQL, PostgreSQL, SQL Server, SQLite3 are supported in master branch and Oracle is supported in oracle branch by database/sql
Xorm AdapterORMCasbinMySQL, PostgreSQL, TiDB, SQLite, SQL Server, Oracle are supported by Xorm
GORM AdapterORMCasbinMySQL, PostgreSQL, Sqlite3, SQL Server are supported by GORM
GORM Adapter ExORMCasbinMySQL, PostgreSQL, Sqlite3, SQL Server are supported by GORM
Ent AdapterORMCasbinMySQL, MariaDB, PostgreSQL, SQLite, Gremlin-based graph databases are supported by ent ORM
Beego ORM AdapterORMCasbinMySQL, PostgreSQL, Sqlite3 are supported by Beego ORM
SQLX AdapterORM@memweyMySQL, PostgreSQL, SQLite, Oracle are supported by SQLX
Sqlx AdapterORM@Blank-XuMySQL, PostgreSQL, SQL Server, SQLite3 are supported in master branch and Oracle is supported in oracle branch by sqlx
GF ORM AdapterORM@vance-liuMySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
GoFrame ORM AdapterORM@kotlin2018MySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
gf-adapterORM@zcycMySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
Gdb AdapterORM@jxo-meMySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
GoFrame V2 AdapterORM@hailazMySQL, SQLite, PostgreSQL, Oracle, SQL Server are supported by GoFrame ORM
Bun AdapterORM@JunNishimuraMySQL, SQLite, PostgreSQL, SQL Server are supported by Bun ORM
Filtered PostgreSQL AdapterSQLCasbinFor PostgreSQL
Filtered pgx AdapterSQL@pckhoiPostgreSQL is supported by pgx
PostgreSQL AdapterSQL@cychiuaeFor PostgreSQL
RQLite AdapterSQLEDOMO SystemsFor RQLite
MongoDB AdapterNoSQLCasbinFor MongoDB based on MongoDB Go Driver
RethinkDB AdapterNoSQL@adityapandey9For RethinkDB
Cassandra AdapterNoSQLCasbinFor Apache Cassandra DB
DynamoDB AdapterNoSQLHOOQFor Amazon DynamoDB
DynacasbinNoSQLNewbMiaoFor Amazon DynamoDB
ArangoDB AdapterNoSQL@adamwasilaFor ArangoDB
Amazon S3 AdapterCloudSolutoFor Minio and Amazon S3
Go CDK AdapterCloud@bartventerAdapter based on Go Cloud Dev Kit that supports: Amazon DynamoDB, Azure CosmosDB, GCP Firestore, MongoDB, In-Memory
Azure Cosmos DB AdapterCloud@spacycoderFor Microsoft Azure Cosmos DB
GCP Firestore AdapterCloud@reedomFor Google Cloud Platform Firestore
GCP Cloud Storage AdapterCloudquramiFor Google Cloud Platform Cloud Storage
GCP Cloud Spanner AdapterCloud@flowerinthenightFor Google Cloud Platform Cloud Spanner
Consul AdapterKV store@ankitm123For HashiCorp Consul
Redis Adapter (Redigo)KV storeCasbinFor Redis
Redis Adapter (go-redis)KV store@mlsenFor Redis
Etcd AdapterKV store@sebastianliuFor etcd
BoltDB AdapterKV store@spezaFor Bolt
Bolt AdapterKV store@wirepairFor Bolt
BadgerDB AdapterKV store@initsFor BadgerDB
Protobuf AdapterStreamCasbinFor Google Protocol Buffers
JSON AdapterStringCasbinFor JSON
String AdapterString@qiangmzsxFor String
HTTP File AdapterHTTP@h4ckednekoFor http.FileSystem
FileSystem AdapterFile@nauconFor fs.FS and embed.FS
备注
  1. 如果使用显式或隐式适配器调用casbin.NewEnforcer(),策略将自动加载。
  2. 您可以调用e.LoadPolicy()从存储中重新加载策略规则。
  3. 如果适配器不支持Auto-Save功能,当您添加或删除策略时,策略规则不能自动保存回存储。 您必须手动调用SavePolicy()来保存所有策略规则。

示例

这里我们提供了几个示例:

文件适配器(内置)

下面展示了如何从内置文件适配器初始化一个执行器:

import "github.com/casbin/casbin"

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

这与下面的内容相同:

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

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

MySQL适配器

下面展示了如何从MySQL数据库初始化一个执行器。 它连接到127.0.0.1:3306上的MySQL DB,使用root和空密码。

import (
"github.com/casbin/casbin"
"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"
"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

适配器有一个叫做Auto-Save的功能。 当一个适配器支持Auto-Save时,意味着它可以支持将单个策略规则添加到存储中,或者从存储中删除单个策略规则。 这与SavePolicy()不同,因为后者会删除存储中的所有策略规则,并将所有Casbin执行器的策略规则保存到存储中。 因此,当策略规则的数量较大时,可能会遇到性能问题。

当适配器支持Auto-Save时,您可以通过Enforcer.EnableAutoSave()函数切换此选项。 该选项默认启用(如果适配器支持)。

备注
  1. Auto-Save功能是可选的。 适配器可以选择实现它或者不实现。
  2. Auto-Save只在Casbin执行器使用的适配器支持它时才起作用。
  3. 查看上面的适配器列表中的AutoSave列,以查看适配器是否支持Auto-Save

这是一个如何使用Auto-Save的示例:

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

// By default, the AutoSave option is enabled for an enforcer.
a := xormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/")
e := casbin.NewEnforcer("examples/basic_model.conf", a)

// Disable the AutoSave option.
e.EnableAutoSave(false)

// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
// it doesn't affect the policy in the storage.
e.AddPolicy(...)
e.RemovePolicy(...)

// Enable the AutoSave option.
e.EnableAutoSave(true)

// Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer,
// but also affects the policy in the storage.
e.AddPolicy(...)
e.RemovePolicy(...)

更多示例,请参见:https://github.com/casbin/xorm-adapter/blob/master/adapter_test.go

如何编写适配器

所有适配器都应实现Adapter接口,至少提供两个必需的方法:LoadPolicy(model model.Model) errorSavePolicy(model model.Model) error

其他三个函数是可选的。 如果适配器支持Auto-Save功能,它们应该被实现。

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

如果适配器不支持Auto-Save,它应该为这三个可选函数提供一个空的实现。 这是一个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执行器在调用这三个可选函数时会忽略not implemented错误。

关于如何编写适配器的详细信息。

  • 数据结构。 适配器应支持至少读取六列。
  • 数据库名称。 默认的数据库名称应该是casbin
  • 表名。 默认的表名应该是casbin_rule
  • Ptype列。 此列的名称应为ptype,而不是p_typePtype
  • 表定义应为(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需要一个filter作为参数。 过滤器应该像这样。
{
"p":[ [ "alice" ], [ "bob" ] ],
"g":[ [ "", "book_group" ], [ "", "pen_group" ] ],
"g2":[ [ "alice" ] ]
}

谁负责创建数据库?

按照惯例,如果数据库不存在,适配器应能够自动创建名为casbin的数据库,并用它来存储策略。 请参考Xorm适配器作为参考实现:https://github.com/casbin/xorm-adapter

上下文适配器

ContextAdapter为Casbin适配器提供了一个上下文感知的接口。

通过上下文,您可以为适配器API实现诸如超时控制等功能

示例

gormadapter支持带有上下文的适配器,以下是使用上下文实现的超时控制

ca, _ := NewContextAdapter("mysql", "root:@tcp(127.0.0.1:3306)/", "casbin")
// Limited time 300s
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多了一层上下文处理,在实现普通Adapter API的基础上,你可以为上下文封装你自己的处理逻辑

简单引用 gormadapteradapter.go