摘要
Casbin 是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。GitHub地址:github.com/casbin ,中文文档地址:casbin.org/docs/zh-CN/… 。casbin对新手而言可以说是比较友好,但网上关于casbin源码剖析相关的文章还是较少,所以特意写这篇文章讲讲casbin的Go源码。阅读本篇文章之前建议先了解casbin的基本原理,会简单的使用casbin
Overall
整体上casbin的源码可以分为enforcer,model,persist,rbac,effector,config,Dispatcher几大模块。下面从一个简单的用例看看casbin的整体执行流程(如下图所示)。这里其实就是根据model创建一个Enforcer对象,然后在整个项目中使用此对象执行casbin操作
Model
从NewModelFromString的具体实现可以看出,Model的构建流程首先是借助config模块解析model conf,解析完后得到一个config对象,然后根据此config对象构造Model,比如此例子解析完之后Model存储的数据大致为{r:{r:&Assertion{Key:"r",Value:"sub, obj, act"}}}...
Model的定义如下:
RBAC
rbac模块其实就是RoleManager,就是角色管理器,对于一些业务,角色之间有比较复杂(例如继承,连接)关系的角色管理器就非常有用
如果在model conf中有定义g = ... 的话,casbin会在Enforcer初始化的时候为g构建一个RoleManager,然后在执行Enforce的时候,使用此rm构建一个回调函数放到govaluate中执行(关于govaluate:darjun.github.io/2020/04/01/… )
Enforcer
在NewEnforcer的时候可以带上构建好的Model以及自选定的持久化Adapter,在casbin文档中也说明了目前支持的Adapter( casbin.org/docs/zh-CN/… )
Enforcer的定义如下图:其中Effector就是效果器,Adapter是策略数据持久化(支持文件,数据库等各种持久化方式),Watcher是多节点的一种同步机制,Dispatcher用于实现casbin多节点之间的最终一致性,RoleManager对于复杂的权限机制非常有用,而Model就是上面NewModelFromString函数构建出来的对象,其缓存了所有策略数据。
Add Or Delete Policies
添加策略数据的具体实现如下,可以看到有dispatcher的时候走dispatcher的添加逻辑,没有dispatcher的话若Model中没缓存当前策略数据则进行缓存,并且需要持久化的话就持久化。有watcher的话还需调watcher进行多节点之间策略数据同步。删除策略数据的时候逻辑也是类似,这里就不再列举
如下图,可以看到往Model中缓存策略数据其实 不是并发安全 的,所以casbin中Enforcer从实现上又分为并发安全的SyncedEnforcer,带缓存的CachedEnforcer等等
Enforce
定义了model conf并创建了Model,然后依据Model又创建了Enforcer,并往Enforcer中添加了策略数据。最后一步就是调用Enforce函数判断当前请求是否有权限,在Enforce函数中主要就是构建了一个enforceParameters对象,然后用govaluate的能力,依据我们model conf中定义的matchers判断是否有策略数据能匹配上当前请求。有的话再调用效果器effector,判断匹配出来的结果是否满足我们预期,在我们的例子中就是判断是否满足 some(where (p.eft == allow))
Enforce的具体实现如下:
Effector
关于Effector,casbin默认的Effector就比较简单,当然casbin也支持自定义Effector,只要实现Effector接口即可
总结
关于casbin的源码部分就讲这么多了,至于SyncedEnforcer,CachedEnforcer等就万变不离其中,这些Enforcer都只是在我们上面讲到的Enforcer基础上做了一些封装然后进行了相应的功能扩展而已。还有casbin的Dispatcher和Watcher我分别在这两篇文章中做了阐述(casbin-watcher机制:juejin.cn/post/709050… ,casbin-Dispatcher: juejin.cn/post/709445… ),Dispatcher和Watcher直接决定了casbin集群的可用性,可以说没有Dispatcher和Watcher,casbin就没法实际应用到项目中来。