id |
---|
casbin |
Casbin middleware for Fiber.
Note: Requires Go 1.18 and above
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/casbin
choose an adapter from here
go get -u github.com/casbin/xorm-adapter
casbin.New(config ...casbin.Config) *casbin.Middleware
Property | Type | Description | Default |
---|---|---|---|
ModelFilePath | string |
Model file path | "./model.conf" |
PolicyAdapter | persist.Adapter |
Database adapter for policies | ./policy.csv |
Enforcer | *casbin.Enforcer |
Custom casbin enforcer | Middleware generated enforcer using ModelFilePath & PolicyAdapter |
Lookup | func(*fiber.Ctx) string |
Look up for current subject | "" |
Unauthorized | func(*fiber.Ctx) error |
Response body for unauthorized responses | Unauthorized |
Forbidden | func(*fiber.Ctx) error |
Response body for forbidden responses | Forbidden |
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/casbin"
_ "github.com/go-sql-driver/mysql"
"github.com/casbin/xorm-adapter/v2"
)
func main() {
app := fiber.New()
authz := casbin.New(casbin.Config{
ModelFilePath: "path/to/rbac_model.conf",
PolicyAdapter: xormadapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/"),
Lookup: func(c *fiber.Ctx) string {
// fetch authenticated user subject
},
})
app.Post("/blog",
authz.RequiresPermissions([]string{"blog:create"}, casbin.WithValidationRule(casbin.MatchAllRule)),
func(c *fiber.Ctx) error {
// your handler
},
)
app.Delete("/blog/:id",
authz.RequiresPermissions([]string{"blog:create", "blog:delete"}, casbin.WithValidationRule(casbin.AtLeastOneRule)),
func(c *fiber.Ctx) error {
// your handler
},
)
app.Listen(":8080")
}
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/casbin"
_ "github.com/go-sql-driver/mysql"
"github.com/casbin/xorm-adapter/v2"
)
func main() {
app := fiber.New()
authz := casbin.New(casbin.Config{
ModelFilePath: "path/to/rbac_model.conf",
PolicyAdapter: xormadapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/"),
Lookup: func(c *fiber.Ctx) string {
// fetch authenticated user subject
},
})
// check permission with Method and Path
app.Post("/blog",
authz.RoutePermission(),
func(c *fiber.Ctx) error {
// your handler
},
)
app.Listen(":8080")
}
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/casbin"
_ "github.com/go-sql-driver/mysql"
"github.com/casbin/xorm-adapter/v2"
)
func main() {
app := fiber.New()
authz := casbin.New(casbin.Config{
ModelFilePath: "path/to/rbac_model.conf",
PolicyAdapter: xormadapter.NewAdapter("mysql", "root:@tcp(127.0.0.1:3306)/"),
Lookup: func(c *fiber.Ctx) string {
// fetch authenticated user subject
},
})
app.Put("/blog/:id",
authz.RequiresRoles([]string{"admin"}),
func(c *fiber.Ctx) error {
// your handler
},
)
app.Listen(":8080")
}
Use this property instead, if you
- manage to test out above example with success
- don't want to expose model and policy to filesystem, thus reveal less and prevent filesystem modifications.
- original casbin.NewEnforcer() supports way more adapters and more ways to initialize *casbin.Enforcer
below example doesn't require ./model.conf
and ./policy.csv
to be present.
package main
import (
...
cb "github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
jsonadapter "github.com/casbin/json-adapter/v2
...
)
const (
rbac_models = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
`
rbac_policy_json = `
[
{"PType":"p","V0":"admin","V1":"blog","V2":"create"},
{"PType":"p","V0":"admin","V1":"blog","V2":"update"},
{"PType":"p","V0":"admin","V1":"blog","V2":"update"},
{"PType":"p","V0":"user","V1":"comment","V2":"read"},
{"PType":"p","V0":"user","V1":"comment","V2":"write"},
{"PType":"p","V0":"admin","V1":"/login","V2":"POST"},
{"PType":"p","V0":"admin","V1":"/blog","V2":"POST"},
{"PType":"p","V0":"admin","V1":"/blog/1","V2":"PUT"},
{"PType":"p","V0":"admin","V1":"/blog/2","V2":"DELETE"},
{"PType":"p","V0":"user","V1":"/comment","V2":"POST"}
]`
)
func main() {
...
m, _ := model.NewModelFromString(rbac_models)
b := []byte(rbac_policy_json)
e, _ := cb.NewEnforcer(m, jsonadapter.NewAdapter(&b))
authz := casbin.New(casbin.Config{Enforcer: e, Lookup: lookupSession})
...
}