咱们来回顾一下上次分享的 GO中 gjson
库的应用和分享,它主要是提供了一种很是快速且简单的方式从json
文档中获取相应值mysql
json
与 gjson
分别表明什么gjson
的简单使用gjson
校验,获取值gjson
的 json 行
gjson
的键路径匹配规则gjson
的修饰符和自定义修饰符要是对 gjson
还有点兴趣的话,能够查看文章 GO中gjson的应用和分享git
今天我们来分享一下 GO里面的权限管理,Casbin
github
通常指根据系统设置的安全规则或者安全策略 算法
用户能够访问并且只能访问本身被受权的资源,很少很多刚恰好sql
权限管理几乎出如今任何系统里面数据库
咱们可能会把 用户身份认证
、 密码加密
、 系统管理
与权限管理弄混淆,那么他们具体的侧重点是什么呢?json
不属于权限管理范畴segmentfault
用户身份认证指的是经过某种凭证来证实本身的身份,例如帐号密码,指纹,人脸识别等等后端
是系统中的一个模块,该模块通常还含有权限管理子模块 , 该模块至关于给权限管理模块提供了一些数据api
也是不属于权限管理范畴 , 他只是用户身份认证领域的一个部分
是 GO 项目的功能强大且高效的开源访问控制库,casbin
支持经常使用的多种访问控制模型,例如:
RBAC
ABAC
ACL
使用casbin
来作权限管理有一个比较好的地方是,casbin
是支持多种语言的,就像protobuf同样也是支持多种语言
{subject, object, action}
,咱们也能够自定义,同时他支持容许受权和拒绝受权
RBAC
中的角色层次结构 中,他能够管理角色用户映射和角色角色映射如root
或administrator
例如 hello/world
,就能够将其映射到 hello*模式
Casbin
的基本模型在 Casbin
库中,他是基于PERM
元模型将访问控制模型抽象为CONF文件,有以下4个部分
一块儿来了解一个最简单的模型,ACL
的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) && r.obj == p.obj && r.act == p.act
例如一个ACL
模型的示例策略
p, xiaomt, data1, read p, xiaomt, data2, write
main.go
文件写gin
对应的接口以及 casbin
的使用rbac_models.conf
RBAC CONF文件
我们写一个路由,里面添加一个拦截器,再写一个接口/api/v1/hello
,使用GET方法验证效果
package main import ( "fmt" "log" "github.com/casbin/casbin" xd "github.com/casbin/xorm-adapter" "github.com/gin-gonic/gin" _ "github.com/go-sql-driver/mysql" ) // myAuth 拦截器 func myAuth(e *casbin.Enforcer) gin.HandlerFunc { return func(c *gin.Context) { obj := c.Request.URL.RequestURI() // 获取方法 act := c.Request.Method sub := "root" // 判断策略是否已经存在了 if ok := e.Enforce(sub, obj, act); ok { log.Println("Check successfully") c.Next() } else { log.Println("sorry , Check failed") c.Abort() } } } func main() { // 使用本身定义rbac_db // 最后的一个参数我们写true ,不然默认为false,使用缺省的数据库名casbin,不存在则建立 a := xd.NewAdapter("mysql", "root:123456@tcp(127.0.0.1:3306)/mycasbin?charset=utf8", true) e := casbin.NewEnforcer("./rbac_models.conf", a) //从DB中 load 策略 e.LoadPolicy() //new 一个路由 r := gin.New() r.POST("/api/v1/add", func(c *gin.Context) { log.Println("add a policy") if ok := e.AddPolicy("root", "/api/v1/hello", "GET"); !ok { log.Println("The strategy already exists") } else { log.Println("add successfully ...") } }) //使用自定义拦截器中间件,每个接口的访问,都会经过这个拦截器 r.Use(myAuth(e)) //建立请求 r.GET("/api/v1/hello", func(c *gin.Context) { fmt.Println("hello wolrd") }) // 监听 127。0.0.1:8888 r.Run(":8888") }
对于上述 xd.NewAdapter
读取数据的操做,我们能够看看具体实现
具体源码在 "github.com/casbin/xorm-adapter"
中的 adapter.go
// NewAdapter is the constructor for Adapter. // dbSpecified is an optional bool parameter. The default value is false. // It's up to whether you have specified an existing DB in dataSourceName. // If dbSpecified == true, you need to make sure the DB in dataSourceName exists. // If dbSpecified == false, the adapter will automatically create a DB named "casbin". func NewAdapter(driverName string, dataSourceName string, dbSpecified ...bool) *Adapter { a := &Adapter{} a.driverName = driverName a.dataSourceName = dataSourceName if len(dbSpecified) == 0 { a.dbSpecified = false } else if len(dbSpecified) == 1 { a.dbSpecified = dbSpecified[0] } else { panic(errors.New("invalid parameter: dbSpecified")) } // Open the DB, create it if not existed. a.open() // Call the destructor when the object is released. runtime.SetFinalizer(a, finalizer) return a }
再来看看casbin.NewEnforcer
源码文件在 "github.com/casbin/casbin"
中 enforcer.go
NewEnforcer
经过文件或 DB 建立一个 enforcer
, 以下是官方的案例写法,注意以下案例
// e := casbin.NewEnforcer("path/to/basic_model.conf", "path/to/basic_policy.csv") // MySQL DB: // a := mysqladapter.NewDBAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/") // e := casbin.NewEnforcer("path/to/basic_model.conf", a)
func NewEnforcer(params ...interface{}) *Enforcer { e := &Enforcer{} parsedParamLen := 0 // 判断参数个数 if len(params) >= 1 { enableLog, ok := params[len(params)-1].(bool) if ok { e.EnableLog(enableLog) parsedParamLen++ } } // 省略 部分代码 return e }
上述代码,你们感兴趣的话,能够将代码贴到本身的环境中
使用相似postman
工具来访问接口,查看效果哦,须要配置好mysql
数据库
对于上述的 gin
和拦截器
若感兴趣的话, 能够查看文章
朋友们,你的支持和鼓励,是我坚持分享,提升质量的动力
好了,本次就到这里,下一次 工做中后端是如何将API提供出去的?swaggo很不错
技术是开放的,咱们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是小魔童哪吒,欢迎点赞关注收藏,下次见~