Passer au contenu principal

Adapters

Dans Casbin, le stockage des politiques est implémenté sous forme d'adaptateur (alias middleware pour Casbin). Un utilisateur de Casbin peut utiliser un adaptateur pour charger des règles de politique à partir d'un stockage (alias LoadPolicy()), ou pour enregistrer des règles de politique dans celui-ci (alias SavePolicy()). Pour rester léger, nous ne mettons pas le code de l'adaptateur dans la bibliothèque principale.

المحولات المدعومة

Une liste complète des adaptateurs Casbin est fournie ci-dessous. Toute contribution de tiers sur un nouvel adaptateur est la bienvenue, veuillez nous en informer et nous l'ajouterons à cette liste :

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
Pgx AdapterSQL@gtoxliliPostgreSQL is supported by pgx, supports customizable column count
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
NATS JetStream AdapterKV storegrepplabsFor NATS JetStream
Kubernetes AdapterCloudgrepplabsFor Kubernetes
note
  1. Si casbin.NewEnforcer() est appelé avec un adaptateur explicite ou implicite, la politique sera chargée automatiquement.
  2. Vous pouvez appeler e.LoadPolicy() pour recharger les règles de politique à partir du stockage.
  3. Si l'adaptateur ne prend pas en charge la fonctionnalité Auto-Save, les règles de politique ne peuvent pas être enregistrées automatiquement dans le stockage lorsque vous ajoutez ou supprimez des politiques. Vous devez appeler SavePolicy() manuellement pour enregistrer toutes les règles de politique.

أمثلة

Voici plusieurs exemples :

محول الملف (مدمج)

Ci-dessous est illustré comment initialiser un enforcer à partir de l'adaptateur de fichier intégré :

import "github.com/casbin/casbin"

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

C'est la même chose que :

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)

Adaptateur MySQL

Ci-dessous est illustré comment initialiser un enforcer à partir de la base de données MySQL. Il se connecte à une base de données MySQL sur 127.0.0.1:3306 avec l'utilisateur root et un mot de passe vide.

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)

Utilisez votre propre adaptateur de stockage.

Vous pouvez utiliser votre propre adaptateur comme ci-dessous :

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

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

Migrer/Convertir entre différents adaptateurs.

Si vous souhaitez convertir l'adaptateur de A à B, vous pouvez procéder comme suit :

  1. Charger la politique de A en mémoire.
e, _ := NewEnforcer(m, A)

ou

e.SetAdapter(A)
e.LoadPolicy()
  1. Convertir votre adaptateur de A à B.
e.SetAdapter(B)
  1. Sauvegarder la politique de la mémoire vers B.
e.SavePolicy()

Charger/Sauvegarder à l'exécution.

Vous pouvez également souhaiter recharger le modèle, recharger la politique ou enregistrer la politique après l'initialisation :

// 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()

حفظ تلقائي

Il existe une fonctionnalité appelée Auto-Save pour les adaptateurs. Lorsqu'un adaptateur prend en charge Auto-Save, cela signifie qu'il peut prendre en charge l'ajout d'une seule règle de politique dans le stockage, ou la suppression d'une seule règle de politique du stockage. Ceci est différent de SavePolicy(), car ce dernier supprimera toutes les règles de politique dans le stockage et enregistrera toutes les règles de politique de l'exécuteur Casbin dans le stockage. Ainsi, cela peut poser des problèmes de performance lorsque le nombre de règles de politique est important.

Lorsque l'adaptateur prend en charge Auto-Save, vous pouvez activer cette option via la fonction Enforcer.EnableAutoSave(). L'option est activée par défaut (si l'adaptateur la prend en charge).

note
  1. La fonctionnalité Auto-Save est facultative. Un adaptateur peut choisir de l'implémenter ou non.
  2. Auto-Save ne fonctionne que pour un enforcer Casbin lorsque l'adaptateur utilisé par l'enforcer le prend en charge.
  3. Consultez la colonne Auto-Save dans la liste des adaptateurs ci-dessus pour voir si Auto-Save est pris en charge par un adaptateur.

Voici un exemple sur la façon d'utiliser 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(...)

Pour plus d'exemples, veuillez consulter : https://github.com/casbin/xorm-adapter/blob/master/adapter_test.go

Comment écrire un adaptateur

Tous les adaptateurs doivent implémenter l'interface Adapter en fournissant au moins deux méthodes obligatoires : LoadPolicy(model model.Model) error et SavePolicy(model model.Model) error.

Les trois autres fonctions sont facultatives. Elles doivent être implémentées si l'adaptateur prend en charge la fonctionnalité Auto-Save.

MéthodeTypeDescription
ChargerPolitique()obligatoireCharger toutes les règles de politique à partir du stockage
SauvegarderPolitique()obligatoireSauvegarder toutes les règles de politique dans le stockage
AjouterPolitique()optionnelAjouter une règle de politique au stockage
RemovePolicy()optionnelإزالة قاعدة سياسة من التخزين
إزالةالسياسةالمصفاة()اختياريإزالة قواعد السياسة التي تطابق الفلتر من التخزين
note

Si un adaptateur ne prend pas en charge Sauvegarde automatique, il doit fournir une implémentation vide pour les trois fonctions optionnelles. إليك مثال لـ 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")
}

Le validateur Casbin ignorera l'erreur non implémenté lors de l'appel de ces trois fonctions optionnelles.

Il y a des détails sur la façon d'écrire un adaptateur.

  • بنية البيانات. L'adaptateur doit prendre en charge la lecture d'au moins six colonnes.
  • اسم قاعدة البيانات. Le nom de la base de données par défaut doit être casbin.
  • اسم الجدول. Le nom de la table par défaut doit être casbin_rule.
  • عمود Ptype. Le nom de cette colonne doit être ptype au lieu de p_type ou Ptype.
  • La définition de la table doit être (id int clé primaire, ptype varchar, v0 varchar, v1 varchar, v2 varchar, v3 varchar, v4 varchar, v5 varchar).
  • L'index de clé unique doit être construit sur les colonnes ptype,v0,v1,v2,v3,v4,v5.
  • LoadFilteredPolicy nécessite un filter en paramètre. يجب أن يكون الفلتر شيئًا مثل هذا.
{
"p": ["", "domain1"],
"g": ["", "", "domain1"]
}

Qui est responsable de créer la base de données (DB) ?

وفقًا للاتفاقية، يجب أن يكون المحول قادرًا على إنشاء قاعدة بيانات تسمى casbin تلقائيًا إذا لم تكن موجودة واستخدامها لتخزين السياسة. Veuillez utiliser l'adaptateur Xorm comme implémentation de référence : https://github.com/casbin/xorm-adapter

Update Adapter

The UpdateAdapter interface extends the basic Adapter interface to support updating policies directly in the storage. This is more efficient than removing and re-adding policies when you need to modify existing rules.

An adapter that implements the UpdateAdapter interface should provide the following methods:

MethodTypeDescription
UpdatePolicy()optionalUpdate a single policy rule in the storage
UpdatePolicies()optionalUpdate multiple policy rules in the storage
UpdateFilteredPolicies()optionalUpdate policy rules that match the filter in the storage

مثال

Here's an example of using the update adapter methods:

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

How to write an update adapter

To implement the UpdateAdapter interface, your adapter needs to implement the update methods in addition to the basic Adapter interface:

// 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 {
// Implementation to update the policy in storage
// For example, in SQL: 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 {
// Implementation to update multiple policies in storage
// This should be done in a transaction 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 {
// Implementation to update filtered policies in storage
// First find policies matching the filter, then update them
return nil
}
note

If an adapter doesn't support the UpdateAdapter interface, Casbin will automatically fall back to using the combination of RemovePolicy() and AddPolicy() operations.

Adaptateur de Contexte

ContextAdapter fournit une interface contextuelle pour les adaptateurs Casbin.

Grâce au contexte, vous pouvez implémenter des fonctionnalités telles que le contrôle du délai d'attente pour l'API de l'Adaptateur.

Example

gormadapter prend en charge l'adaptateur avec contexte, ci-dessous un exemple de contrôle du délai d'attente implémenté à l'aide du contexte.

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)
}

كيفية كتابة محول سياق

L'API ContextAdapter a seulement une couche supplémentaire de traitement de contexte par rapport à l'API Adapter ordinaire,

Une référence simple à gormadapter : adapter.go

Transaction

Casbin now supports Transactions. Here's an example about how to use Transaction in 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.
// If the function returns an error, the transaction is rolled back.
// Otherwise, it's committed automatically.
err := e.WithTransaction(ctx, func(tx *casbin.Transaction) error {
tx.AddPolicy("alice", "data1", "read")
tx.AddPolicy("alice", "data1", "write")
return nil
})

// If you wish to manually handle the transaction
tx, _ := e.BeginTransaction(ctx)
tx.AddPolicy("alice", "data1", "write")
if err := tx.Commit(); err != nil {
// handle if transaction failed
}

To add this capability to your adapter, you need to implement TransactionalAdapter and TransactionContext in persist/transaction.go.

Code reference to the gormadapter: adapter.go