はじめに
インストール
- Go
- Java
- Node.js
- PHP
- Python
- .NET
- C++
- Rust
- Delphi
- Lua
go get github.com/casbin/casbin/v2
For Maven:
<!-- https://mvnrepository.com/artifact/org.casbin/jcasbin -->
<dependency>
<groupId>org.casbin</groupId>
<artifactId>jcasbin</artifactId>
<version>1.x.y</version>
</dependency>
# NPM
npm install casbin --save
# Yarn
yarn add casbin
プロジェクトの composer.json
でこのパッケージを必要とします。 パッケージをダウンロードします:
composer require casbin/casbin
pip install casbin
dotnet add package Casbin.NET
# download source
git clone https://github.com/casbin/casbin-cpp.git
# generate project files
cd casbin-cpp && mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release
# build and install casbin
cmake --build . --config Release --target casbin install -j 10
cargo install cargo-edit
cargo add casbin
// If you use async-std as async executor
cargo add async-std
// If you use tokio as async executor
cargo add tokio // make sure you activate its `macros` feature
Casbin4Dはパッケージ(現在はDelphi 10.3 Rio用) 内にあり、IDEにインストールできます。 ただし、ビジュアルコンポーネントはないため、パッケージから独立した形でそのユニットを使用します。 プロジェクトにユニットをインポートするだけです(数字を気にしないと仮定します)。
luarocks install casbin
エラーが発生した場合:/usr/local/lib/luarocks/rocksへの書き込み権限がない場合は、特権ユーザとして実行するか、--localを指定してローカルツリーを使用すると良いでしょう。 次のようにコマンドの後ろに --local を付けて修正できます。
luarocks install casbin --local
Casbin Enforcerを作成する
Casbinは、アクセス制御モデルを設定するために設定ファイルを使用します。
model.conf
と policy.csv
の2つの設定ファイルがあります。 model.conf
はアクセスモデルを保存し、 policy.csv
は特定のユーザー権限設定を保存します。 Casbinの利用方法は非常に洗練されています。 基本的には、1つの主要となる構造体が必要となります。それが enforcer です。 この構造体を構築するとき、 model.conf
と policy.csv
がロードされます。
言い換えると、Casbin Enforcer を作成するには、 Model と Adapter を提供する必要があります。
Casbin has a FileAdapter, see Adapter for more information.
- Modelファイルとデフォルトの FileAdapter を使用する:
- Go
- Java
- Node.js
- PHP
- Python
- .NET
- C++
- Delphi
- Rust
- Lua
import "github.com/casbin/casbin/v2"
e, err := casbin.NewEnforcer("path/to/model.conf", "path/to/policy.csv")
import org.casbin.jcasbin.main.Enforcer;
Enforcer e = new Enforcer("path/to/model.conf", "path/to/policy.csv");
import { newEnforcer } from 'casbin';
const e = await newEnforcer('path/to/model.conf', 'path/to/policy.csv');
require_once './vendor/autoload.php';
use Casbin\Enforcer;
$e = new Enforcer("path/to/model.conf", "path/to/policy.csv");
import casbin
e = casbin.Enforcer("path/to/model.conf", "path/to/policy.csv")
using NetCasbin;
var e = new Enforcer("path/to/model.conf", "path/to/policy.csv");
#include <iostream>
#include <casbin/casbin.h>
int main() {
// Create an Enforcer
casbin::Enforcer e("path/to/model.conf", "path/to/policy.csv");
// your code ..
}
var
casbin: ICasbin;
begin
casbin := TCasbin.Create('path/to/model.conf', 'path/to/policy.csv');
...
end
use casbin::prelude::*;
// If you use async_td as async executor
#[cfg(feature = "runtime-async-std")]
#[async_std::main]
async fn main() -> Result<()> {
let mut e = Enforcer::new("path/to/model.conf", "path/to/policy.csv").await?;
Ok(())
}
// If you use tokio as async executor
#[cfg(feature = "runtime-tokio")]
#[tokio::main]
async fn main() -> Result<()> {
let mut e = Enforcer::new("path/to/model.conf", "path/to/policy.csv").await?;
Ok(())
}
local Enforcer = require("casbin")
local e = Enforcer:new("path/to/model.conf", "path/to/policy.csv") -- The Casbin Enforcer
- 他のAdapterとともにModelテキストを使用する:
- Go
- Python
import (
"log"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v2"
_ "github.com/go-sql-driver/mysql"
)
// Initialize a Xorm adapter with MySQL database.
a, err := xormadapter.NewAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/casbin")
if err != nil {
log.Fatalf("error: adapter: %s", err)
}
m, err := model.NewModelFromString(`
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
`)
if err != nil {
log.Fatalf("error: model: %s", err)
}
e, err := casbin.NewEnforcer(m, a)
if err != nil {
log.Fatalf("error: enforcer: %s", err)
}
import casbin
import casbin_sqlalchemy_adapter
# Use SQLAlchemy Casbin adapter with SQLLite DB
adapter = casbin_sqlalchemy_adapter.Adapter('sqlite:///test.db')
# Create a config model policy
with open("rbac_example_model.conf", "w") as f:
f.write("""
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
""")
# Create enforcer from adapter and config policy
e = casbin.Enforcer('rbac_example_model.conf', adapter)
権限のチェックする
アクセスが発生する直前のコードにEnforcementフックを追加する:
- Go
- Java
- Node.js
- PHP
- Python
- .NET
- C++
- Delphi
- Rust
- Lua
sub := "alice" // リソースにアクセスしたいユーザ
obj := "data1" // アクセスされるリソース
act := "read" // ユーザーがリソースに対して実行する操作
ok, err := e.Enforce(sub, obj, act)
if err != nil {
// エラーハンドリング
}
if ok == true {
// aliceがdata1を閲覧することを許可する
} else {
// リクエストを拒否し、エラーを表示する
}
// 複数のリクエストを一括で処理するのに BatchEnforce() を使用することも可能です。
// このメソッドはboolのsliceを返却します。このsliceのインデックスは2次元配列の行のインデックスに対応しています。
// e.g. results[0] is the result of {"alice", "data1", "read"}
results, err := e.BatchEnforce([][]interface{}{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"jack", "data3", "read"}})
String sub = "alice"; // リソースにアクセスしたいユーザ
String obj = "data1"; // アクセスされるリソース
String act = "read"; // ユーザーがリソースに対して実行する操作
if (e.enforce(sub, obj, act) == true) {
// aliceがdata1を閲覧することを許可する
} else {
// リクエストを拒否し、エラーを表示する
}
const sub = 'alice'; // リソースにアクセスしたいユーザ
const obj = 'data1'; // アクセスされるリソース
const act = 'read'; // ユーザーがリソースに対して実行する操作
if ((await e.enforce(sub, obj, act)) === true) {
// aliceがdata1を閲覧することを許可する
} else {
// リクエストを拒否し、エラーを表示する
}
$sub = "alice"; // リソースにアクセスしたいユーザ
$obj = "data1"; // アクセスされるリソース
$act = "read"; // ユーザーがリソースに対して実行する操作
if ($e->enforce($sub, $obj, $act) === true) {
// aliceがdata1を閲覧することを許可する
} else {
// リクエストを拒否し、エラーを表示する
}
sub = "alice" # リソースにアクセスしたいユーザ
obj = "data1" # アクセスされるリソース
act = "read" # ユーザーがリソースに対して実行する操作
if e.enforce(sub, obj, act):
# aliceがdata1を閲覧することを許可する
pass
else:
# リクエストを拒否し、エラーを表示する
pass
var sub = "alice"; # リソースにアクセスしたいユーザ
var obj = "data1"; # アクセスされるリソース
var act = "read"; # ユーザがリソースに対して実行する操作
if (await e.EnforceAsync(sub, obj, act))
{
// aliceがdata1を閲覧することを許可する
}
else
{
// リクエストを拒否し、エラーを表示する
}
casbin::Enforcer e("../assets/model.conf", "../assets/policy.csv");
if (e.Enforce({"alice", "/alice_data/hello", "GET"})) {
std::cout << "Enforce OK" << std::endl;
} else {
std::cout << "Enforce NOT Good" << std::endl;
}
if (e.Enforce({"alice", "/alice_data/hello", "POST"})) {
std::cout << "Enforce OK" << std::endl;
} else {
std::cout << "Enforce NOT Good" << std::endl;
}
if casbin.enforce(['alice,data1,read']) then
// Alice is super happy as she can read data1
else
// Alice is sad
let sub = "alice"; // リソースにアクセスしたいユーザ
let obj = "data1"; // アクセスされるリソース
let act = "read"; // ユーザーがリソースに対して実行する操作
if e.enforce((sub, obj, act)).await? {
// aliceがdata1を閲覧することを許可する
} else {
// エラーが発生
}
if e:enforce("alice", "data1", "read") then
-- aliceがdata1を閲覧することを許可する
else
-- リクエストを拒否し、エラーを表示する
end
Casbinは実行時の権限管理用のAPIも提供しています。 例えば、ユーザーに割り当てられたすべてのロールを以下のように取得できます。
- Go
- Java
- Node.js
- PHP
- Python
- .NET
- Delphi
- Rust
- Lua
roles, err := e.GetRolesForUser("alice")
List<String> roles = e.getRolesForUser("alice");
const roles = await e.getRolesForUser('alice');
$roles = $e->getRolesForUser("alice");
roles = e.get_roles_for_user("alice")
var roles = e.GetRolesForUser("alice");
roles = e.rolesForEntity("alice")
let roles = e.get_roles_for_user("alice");
local roles = e:GetRolesForUser("alice")
詳細については、 Management API および RBAC API を参照してください。
その他の詳細はテストケースも参照してみてください。