以下の内容はhttps://timtoronto634.hatenablog.com/entry/2024/10/06/160323より取得しました。


Casbin のチュートリアル + α で本番で使えるようにする

casbin を使って web application の認可を行おうとする場合、使い方の例が少なく、混乱する。

基本

How It Works | Casbin

このページの例を少し広げると、以下のような設定になる

import "github.com/casbin/casbin/v2"

e, err := casbin.NewEnforcer("path/to/model.conf", "path/to/policy.csv")
# model.conf
[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
#policy.csv
p, admin, data1, read
p, admin, data1, write
p, admin, data2, read
p, admin, data2, write
p, stuff, data1, read
p, stuff, data2, read
p, customer, data1, read
g, alice, admin
g, bob, stuff
g, charlie, customer
p, david, data2, read

data1 が顧客情報で、data2 が製品情報だとすれば、

  • 管理者 (admin) は顧客/製品情報 を閲覧できて操作できる。
  • 編集者 (seller) は顧客/製品情報 を閲覧できるが、編集はできない。
  • 顧客 (customer) は製品情報を閲覧できるが、顧客情報にアクセスしたり、何かのデータを編集はできない
  • david は特別に製品情報を閲覧可能

といった認可が実現できる。

困ること

上記の例だと、alice, bob は csv ファイル上に定義してあるので、ユーザー数が不定のサービス提供においては運用に耐えない。

新しい契約をとるたびにファイルを編集したり、csv のファイルの読み書きを行うわけにはいかない。

一つの解決策はそれぞれのユーザーがどの権限(admin, seller customer) なのかを独自に database に保持する方法である。

CREATE TABLE roles (
  id uuid NOT NULL,
  user_id uuid references users(id),
  role string NOT NULL,
);
role, err := db.GetUserRole(ctx, userID)
if err != {
  // todo: error handle
}

allowed, err := e.enforce(role, data1, "read")
if err != nil {
  // todo: error handle
}

if (!allowed) {
  w.WriteHeader(http.StatusForbidden)
  return 
}

これで endpoint ごとの policy を定義しておけば、認可判断を行うことができる

他の解決策

ユーザーがどの権限(admin, seller customer) なのかを casbin に管理させることもできる。

この方法を取ると、より柔軟な RBAC を実装できる。

詳細は document 参照のこと。

Policy Storage | Casbin

この方法も万能ではなく、カラム名を自由に命名できなかったり、パフォーマンス上のチューニングが必要なことが指摘されている。




以上の内容はhttps://timtoronto634.hatenablog.com/entry/2024/10/06/160323より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14