多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## casbin介绍 详细介绍: https://www.kancloud.cn/oldlei/casbin/1289454 `casbin`是由北大的一位博士生主导开发的一个基于`Go`语言的权限控制库。支持`ACL`,`RBAC`,`ABAC`等常用的访问控制模型。 `casbin`是`Golang`项目的强大而高效的开源访问控制库。 它支持基于各种访问控制模型实施授权。 `casbin`的核心是一套基于`PERM metamodel`(`Policy`,`Effect`,`Request`,`Matchers`)的`DSL`。`Casbin`从用这种`DSL`定义的配置文件中读取访问控制模型,作为后续权限验证的基础 ## Casbin做了什么 * 支持自定义请求的格式,默认的请求格式为`{subject, object, action}`。 * 具有访问控制模型`model`和策略`policy`两个核心概念。 * 支持`RBAC`中的多层角色继承,不止主体可以有角色,资源也可以具有角色。 * 支持超级用户,如`root`或`Administrator`,超级用户可以不受授权策略的约束访问任意资源。 * 支持多种内置的操作符,如`keyMatch`,方便对路径式的资源进行管理,如`/foo/bar`可以映射到`/foo*` ## Casbin不做的事情 * 身份认证`authentication`(即验证用户的用户名、密码),`casbin`只负责访问控制。应该有其他专门的组件负责身份认证,然后由`casbin`进行访问控制,二者是相互配合的关系。 * 管理用户列表或角色列表。`Casbin`认为由项目自身来管理用户、角色列表更为合适,用户通常有他们的密码,但是`Casbin`的设计思想并不是把它作为一个存储密码的容器。而是存储`RBAC`方案中用户和角色之间的映射关系。 ## 配置示例 ### 模型与策略定制 ``` //sub "alice"// 想要访问资源的用户. //obj "data1" // 要访问的资源. //act "read" // 用户对资源执行的操作. # Request definition [request_definition] r = sub, obj, act # Policy definition [policy_definition] p = sub, obj, act # Policy effect [policy_effect] e = some(where (p.eft == allow)) # Matchers [matchers] m = r.sub == p.sub && r.obj == p.obj && r.act == p.act ``` 可以看到这个配置文件主要定义了`Request`和`Policy`的组成结构.`Policy effect`和`Matchers`则灵活的多,可以包含一些自定义的表达式比如我们要加入一个名叫`root`的超级管理员,就可以这样写: ~~~ [matchers]m = r.sub == p.sub && r.obj == p.obj && r.act == p.act || r.sub == "root" ~~~ 又比如我们可以用正则匹配来判断权限是否匹配: ~~~ [matchers]m = r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act) ~~~ ### 具体规则设置 ~~~ p, alice, data1, read p, bob, data2, write ~~~ > 意思就是 alice 可以读 data1,bob 可以写 data2 ``` //配置 [request_definition] //请求定义 r = sub, obj, act [policy_definition] //策略定义,也就是*.cvs文件 p 定义的格式 p = sub, obj, act [role_definition] //组定义,也就是*.cvs文件 g 定义的格式 g = _, _ [policy_effect] e = some(where (p.eft == allow)) [matchers] //满足条件 m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") //请求用户与满足*.cvs p(策略)且满足g(组规则)且请求资源满足p(策略)规定资源 ``` ``` //policy策略 p, alice, /dataset1/*, GET //alice 用户有对 method为GET路径满足 /dataset1/*的访问权限 下面同理 p, alice, /dataset1/resource1, POST p, bob, /dataset2/resource1, * p, bob, /dataset2/resource2, GET p, bob, /dataset2/folder1/*, POST p, cathrin, /dataset2/resource2, GET p, dataset1_admin, /dataset1/*, * g, cathrin, dataset1_admin //cathrin用户属于dataset1_admin组,也就是dataset1_admin能访问的cathrin都能访问,反之不然 ``` ## 示例 > 模型与策略定制casbinmodel.conf ~~~ [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) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*") ~~~ > 具体规则设置casbinpolicy.csv ~~~ p, alice, /dataset1/*, GET p, alice, /dataset1/resource1, POST p, bob, /dataset2/resource1, * p, bob, /dataset2/resource2, GET p, bob, /dataset2/folder1/*, POST ~~~ ## iris示例代码 ~~~ package main import ( "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/middleware/basicauth" "github.com/iris-contrib/middleware/casbin" ) // $ go get github.com/casbin/casbin/v2@v2.17.0 // $ go run main.go func newApp() *iris.Application { app := iris.New() casbinMiddleware, err := casbin.NewEnforcer("casbinmodel.conf", "casbinpolicy.csv") if err != nil { panic(err) } /* The Casbin authorization determines a request based on `{subject, object, action}`. Please refer to: https://github.com/casbin/casbin to understand how it works first. The object is the current request's path and the action is the current request's method. The subject is extracted by the current request's ctx.User().GetUsername(), you can customize it by: 1. casbinMiddleware.SubjectExtractor = func(ctx iris.Context) string { // [...custom logic] return "bob" } 2. by SetSubject package-level function: func auth(ctx iris.Context) { casbin.SetSubject(ctx, "bob") ctx.Next() } */ app.Use(basicauth.Default(map[string]string{ "bob": "bobpass", "alice": "alicepass", })) app.Use(casbinMiddleware.ServeHTTP) app.Get("/", hi) app.Get("/dataset1/{p:path}", hi) // p, alice, /dataset1/*, GET app.Post("/dataset1/resource1", hi) app.Get("/dataset2/resource2", hi) app.Post("/dataset2/folder1/{p:path}", hi) app.Any("/dataset2/resource1", hi) return app } func main() { app := newApp() app.Listen(":8080") } func hi(ctx iris.Context) { ctx.Writef("Hello %s", casbin.Subject(ctx)) // Note that, by default, the username is extracted by ctx.User().GetUsername() // to change that behavior modify the `casbin.SubjectExtractor` or // use the `casbin.SetSubject` to set a custom subject for the current request // before the casbin middleware's execution. } ~~~