这篇博客还是整理从https://github.com/LyricTian/gin-admin 这个项目中学习的golang相关知识。

作者在项目中使用了 github.com/casbin/casbin 进行权限控制的,这个库自己之前也没有用过,正好可以通过这个项目学习一下使用。 当然这篇博客并不会对casbin的使用做非常详细的说明,感兴趣的可以去官网看具体的使用文档。

关于casbin


常见访问控制模型

ABAC: 基于属性的访问控制。

DAC: 自主访问控制模型(DAC,Discretionary Access Control)是根据自主访问控制策略建立的一种模型,允许合法用户以用户或用户组的身份访问策略规定的客体,同时阻止非授权用户访问客体。拥有客体权限的用户,可以将该客体的权限分配给其他用户。

ACL:  ACL是最早也是最基本的一种访问控制机制,它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD中的那些操作。当系统试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。总得来说,ACL是一种面向资源的访问控制模型,它的机制是围绕“资源”展开的。

RBAC: 基于角色的访问控制(RBAC, Role Based Access Control)在用户和权限之间引入了“角色(Role)”的概念,角色解耦了用户和权限之间的关系。

casbin

casbin使用配置文件来设置访问控制模型。在 Casbin 中, 访问控制模型被抽象为基于 PERM (Policy, Effect, Request, Matcher) 的一个文件。

Casbin中最基本、最简单的model是ACL。ACL中的model CONF为:

# 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 definition: 代表请求,上面的配置中 r = sub, obj, act 代表一个请求有三个标准元素:请求主体,请求对象,请求操作。

Policy definition: 代表策略,表示具体的权限定义的规则是什么,上面配置中 p = sub, obj, act

Policy effect: Effect 用来判断如果一个请求满足了规则,是否需要同意请求

Matchers: 有请求,有规则,那么请求是否匹配某个规则,则是matcher进行判断的

ACL with superuser 栗子

model的配置:

[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 || r.sub == "root"

Policey 配置:

p, alice, data1, read
p, bob, data2, write

当我们请求:alice,data1,read

根据匹配规则,匹配的结果就是true

当我们请求:alice,data1,write

根据匹配规则,匹配的规则就是false

RESful (KeyMatch2) 栗子

model的配置:

[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 && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)

Policy 定义:

p, alice, /alice_data/:resource, GET
p, alice, /alice_data2/:id/using/:resId, GET

当我们请求 alice, /alice_data/hello, GET 根据matchers规则匹配了 p, alice, /alice_data/:resource, GET 所以返回true

当我们请求 alice, /alice_data/hello, POST 根据matchers规则没有匹配到,所以返回false

RBAC 栗子

model的配置:

[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

在这里引入了role_definition 角色定义, g 用于判断哪个用户是否属于哪个角色

Policy 配置:

p, alice, data1, read
p, bob, data2, write
p, data2_admin, data2, read
p, data2_admin, data2, write g, alice, data2_admin

当我们请求 alice, data2, read 根据matchers 匹配了alice 是data2_admin角色,并且 r.obj == p.obj && r.act == p.act 所以返回true

在gin-admin项目中的使用

这里先梳理一下作者代码中对casbin的使用,因为之前看了casbin在其他几个项目中的使用,感觉都是有点乱,在在gin-admin这个项目的时候一开始也是感觉有点懵 ,没有理解怎么用,不过当把代码梳理清楚之后,感觉gin-admin作者的使用还是非常好的。

gin-admin项目中关于casbin的使用分为

  1. 定义CasbinAdapter
  2. 初始化casbin
  3. 异步加载casbin权限

定义了CasbinAdapter

作者在gin-admin/internal/module/adapter/casbin.go 中定义了CasbinAdapter:

// CasbinAdapter casbin适配器
type CasbinAdapter struct {
RoleModel model.IRole
RoleMenuModel model.IRoleMenu
MenuResourceModel model.IMenuActionResource
UserModel model.IUser
UserRoleModel model.IUserRole
}

这里的CasbinAdapter是实现了casbin中的Adapter接口,即CasbinAdapter实现了LoadPolicy,SavePolicy,AddPolicy,RemovePolicy方法,并且作者通过在LoadPolicy将用户权限和角色权限从数据库中进行加载。

初始化

权限的初始化是通过下面代码:

func InitCasbin(adapter persist.Adapter) (*casbin.SyncedEnforcer, func(), error) {
cfg := config.C.Casbin
if cfg.Model == "" {
return new(casbin.SyncedEnforcer), nil, nil
} e, err := casbin.NewSyncedEnforcer(cfg.Model)
if err != nil {
return nil, nil, err
}
e.EnableLog(cfg.Debug)
err = e.InitWithModelAndAdapter(e.GetModel(), adapter)
if err != nil {
return nil, nil, err
}
e.EnableEnforce(cfg.Enable) cleanFunc := func() {}
if cfg.AutoLoad {
e.StartAutoLoadPolicy(time.Duration(cfg.AutoLoadInternal) * time.Second)
cleanFunc = func() {
e.StopAutoLoadPolicy()
}
} return e, cleanFunc, nil
}

异步加载casbin权限

这个部分主要是当我们通过页面进行权限的配置后,我们需要将权限重新进行加载,这部分代码在gin-admin/internal/app/bll/impl/bll/b_casbin.go中:

var chCasbinPolicy chan *chCasbinPolicyItem

type chCasbinPolicyItem struct {
ctx context.Context
e *casbin.SyncedEnforcer
} func init() {
chCasbinPolicy = make(chan *chCasbinPolicyItem, 1)
go func() {
for item := range chCasbinPolicy {
err := item.e.LoadPolicy()
if err != nil {
logger.Errorf(item.ctx, "The load casbin policy error: %s", err.Error())
}
}
}()
} // LoadCasbinPolicy 异步加载casbin权限策略
func LoadCasbinPolicy(ctx context.Context, e *casbin.SyncedEnforcer) {
if !config.C.Casbin.Enable {
return
} if len(chCasbinPolicy) > 0 {
logger.Infof(ctx, "The load casbin policy is already in the wait queue")
return
} chCasbinPolicy <- &chCasbinPolicyItem{
ctx: ctx,
e: e,
}
}

而在我们的更改权限的接口中都会通过调用LoadCasbinPolicy将权限策略进行加载。

总结

关于这个项目整理了三篇文章,也学习到了很多东西,其实到这篇文章,作者整体代码自己已经树立清楚了,很多人会觉得作者的项目目录过于复杂,还有一些重复代码,在你刚开始梳理代码逻辑的时候还会感到一脸懵,但是当你耐心梳理完之后,你会发现,这样写原来会有这样或者那样的好处。作者剩余的代码就是关于web接口中的逻辑了,就不在做整理。

后面的计划是通过这次对这次代码的学习,写一个blog的web项目。同时也会找下一个开源项目代码进行学习

延伸阅读

从别人的代码中学习golang系列--03的更多相关文章

  1. 从别人的代码中学习golang系列--01

    自己最近在思考一个问题,如何让自己的代码质量逐渐提高,于是想到整理这个系列,通过阅读别人的代码,从别人的代码中学习,来逐渐提高自己的代码质量.本篇是这个系列的第一篇,我也不知道自己会写多少篇,但是希望 ...

  2. 从别人的代码中学习golang系列--02

    这篇博客还是整理从https://github.com/LyricTian/gin-admin 这个项目中学习的golang相关知识 作者在项目中使用了https://github.com/googl ...

  3. 在C#代码中应用Log4Net系列教程

    在C#代码中应用Log4Net系列教程(附源代码)   Log4Net应该可以说是DotNet中最流行的开源日志组件了.以前需要苦逼写的日志类,在Log4Net中简单地配置一下就搞定了.没用过Log4 ...

  4. 在C#代码中应用Log4Net系列教程(附源代码)

    Log4Net应该可以说是DotNet中最流行的开源日志组件了.以前需要苦逼写的日志类,在Log4Net中简单地配置一下就搞定了.没用过Log4Net,真心不知道原来日志组件也可以做得这么灵活,当然这 ...

  5. [转]在C#代码中应用Log4Net系列教程(附源代码)

    Log4Net应该可以说是DotNet中最流行的开源日志组件了.以前需要苦逼写的日志类,在Log4Net中简单地配置一下就搞定了.没用过Log4Net,真心不知道原来日志组件也可以做得这么灵活,当然这 ...

  6. NeteaseCloudWebApp模仿网易云音乐的vue自己从开源代码中学习到的

    github地址: https://github.com/javaSwing/NeteaseCloudWebApp 1.Vue.prototype.$http = Axios // 类似于vue-re ...

  7. 在C#代码中应用Log4Net系列教程(附源代码)地址

    在博客园看到一篇关于Log4Net使用教程,比较详细,感谢这位热心的博主 博客园地址:http://www.cnblogs.com/kissazi2/archive/2013/10/29/339359 ...

  8. WebService学习笔记系列(二)

    soap(简单对象访问协议),它是在http基础之上传递xml格式数据的协议.soap协议分为两个版本,soap1.1和soap1.2. 在学习webservice时我们有一个必备工具叫做tcpmon ...

  9. log4net保存到数据库系列三、代码中xml配置log4net

    园子里面有很多关于log4net保存到数据库的帖子,但是要动手操作还是比较不易,从头开始学习log4net数据库日志一.WebConfig中配置log4net 一.WebConfig中配置log4ne ...

随机推荐

  1. 洛谷CF997A:Convert to Ones

    温馨提示: 本题适合先思考再看题解,相信各位神犇都能轻轻松松过掉它. 题目链接: https://www.luogu.com.cn/problem/CF997A 分析: 首先要读懂题,to ones, ...

  2. 用Python语言绘制股市OBV指标效果

    我的新书<基于股票大数据分析的Python入门实战>于近日上架,在这篇博文向大家介绍我的新书:<基于股票大数据分析的Python入门实战>里,介绍了这本书的内容.这里将摘录出部 ...

  3. 【MySQL】Merge Index导致死锁

    水稻:最近有个朋友生产环境出现MySQL死锁问题,一听是死锁,那必须去看看啊,于是饶(si)有(qu)兴(huo)致(lai)的研究了好几天 菜瓜:MySQL死锁,赶紧分享一下 水稻:能否先让我装完X ...

  4. Linux下diff命令用法详解

    大家好,我是良许. 我们在平时工作的时候,经常要知道两个文件之间,以及同个文件不同版本之间有何异同点.在 Windows 下,有 beyond compare 这个好用的工具,而在 Linux 下,也 ...

  5. python 并发专题(一):并发基础相关概念,术语等

    一.线程 1.概念 线程是程序执行流的最小执行单位,是行程中的实际运作单位. 进程是一个动态的过程,是一个活动的实体.简单来说,一个应用程序的运行就可以被看做是一个进程,而线程,是运行中的实际的任务执 ...

  6. Python之函数、递归、内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  7. 保存与恢复变量和模型,tensorflow官方文档阅读笔记

    官方中文文档的网址先贴出来:https://tensorflow.google.cn/programmers_guide/saved_model tf.train.Saver 类别提供了保存和恢复模型 ...

  8. winserver2008R2安装配置JDK+tomcat之坑

    记一次winserver安装jdk+tomcat 准备软件: jdk-8u241-windows-x64 apache-tomcat-8.5.46-windows-x64 一.安装java 1.安装j ...

  9. Java8——Stream流

    Stream是数据渠道,用于操作集合.数组等生成的元素序列. Stream操作的三个步骤: 创建Stream 中间操作 终止操作 一.获取stream的四种方式 通过collection系列集合的st ...

  10. 012.Nginx负载均衡

    一 负载均衡概述 1.1 负载均衡介绍 负载均衡是将负载分摊到多个操作单元上执行,从而提高服务的可用性和响应速度,带给用户更好的体验.对于Web应用,通过负载均衡,可以将一台服务器的工作扩展到多台服务 ...