Casbin 是一个强大的,开源的访问控制框架,权限管理机制支持多种访问控制模型; 并且支持多种编程语言;

文档地址:https://casbin.org/docs/zh-CN/overview

Gin Golang 的 Web 框架,短小精悍

文档地址: https://gin-gonic.com/docs/

Gorm Golang 的 ORM 框架

文档地址:http://gorm.book.jasperxu.com/

今天我们要学习的是如何通过Casbin 来控制开发的 API 访问权限

##### Casbin 工作原理

访问控制模型被抽象为PERM(Policy,Effect,Request,Matcher) 的一个文件,如果切换项目的授权机制只用修改文件即可;

Policy: 定义权限的规则

Effect: 定义组合多个Policy 后是允许还是拒绝(allow/deny)

Request: 访问的请求,可以理解为谁想访问什么资源

Matcher:判断Request 是否满足Policy ,返回true或false

##### 在使用Casbin 控制后台接口时使用以下模型

[request_definition]
r = sub, obj, act
# 请求的规则
# r 是规则的名称,sub 为请求的实体,obj 为资源的名称, act 为请求的实际操作动作
[policy_definition]
p = sub, obj, act
# 策略的规则
# 同请求
[role_definition]
g = _, _
# 角色的定义
# g 角色的名称,第一个位置为用户,第二个位置为角色,第三个位置为域(在多租户场景下使用)
[policy_effect]
e = some(where (p.eft == allow))
# 任意一条 policy rule 满足, 则最终结果为 allow
[matchers]
m = g(r.sub, p.sub) == true \
&& keyMatch2(r.obj, p.obj) == true \
&& regexMatch(r.act, p.act) == true \
|| r.sub == "root"
# 前三个用来匹配上面定义的请求的规则, 最后一个或条件为:如果实体是root 直接通过, 不验证权限

在理解了Casbin 的工作原理后,实际写代码测试一下

需要使用的外部包

go get github.com/casbin/casbin  Casbin 官方库

go get github.com/casbin/gorm-adapter  Casbin 插件,用来将规则和策略保存到数据库中

go get github.com/gin-gonic/gin  Go Web 框架

go get github.com/go-sql-driver/mysql  Go MySQL 驱动

go get github.com/jinzhu/gorm  Go ORMpackage mainimport (    "fmt"    "github.com/casbin/casbin"

    "github.com/casbin/gorm-adapter"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
)

// 统一响应结构体
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
} var O *gorm.DB
var PO *gormadapter.Adapter
var Enforcer *casbin.Enforcer


func ping(c *gin.Context) {
var response Response
response.Code = 0
response.Message = "success"
response.Data = ""
c.JSON(200, response)
return
}
// 数据库连接及角色规则的初始化
func connect() {
dsn := "xxx:xxx@(xxxx:3xx6)/goapp?charset=utf8&parseTime=True&loc=Local"
var err error
O, err = gorm.Open("mysql", dsn)
if err != nil {
fmt.Println("connect DB error")
panic(err)
}
   // 将数据库连接同步给插件, 插件用来操作数据库
PO = gormadapter.NewAdapterByDB(O)
// 这里也可以使用原生字符串方式
//
Enforcer = casbin.NewEnforcer("./auth_model.conf", PO)
// 开启权限认证日志
Enforcer.EnableLog(true)
// 加载数据库中的策略
err = Enforcer.LoadPolicy()
if err != nil {
fmt.Println("loadPolicy error")
panic(err)
}
// 创建一个角色,并赋于权限
// admin 这个角色可以访问GET 方式访问 /api/v2/ping
res := Enforcer.AddPolicy("admin","/api/v2/ping","GET")
if !res {
fmt.Println("policy is exist")
} else {
fmt.Println("policy is not exist, adding")
}
// 将 test 用户加入一个角色中
Enforcer.AddRoleForUser("test","root")
Enforcer.AddRoleForUser("tom","admin")
// 请看规则中如果用户名为 root 则不受限制
}
func main() {
defer O.Close()
connect()
g := gin.Default()
  // 这里的接口没有使用权限认证中间件
version1 := g.Group("/api/v1")
{
version1.GET("/ping", ping) // 这个是通用的接口
}
// 接口使用权限认证中间件
version2 := g.Group("/api/v2", CasbinMiddleWare)
{
version2.GET("/ping", ping)
}
_ = g.Run(":8099")
} // casbin middleware 权限认证中间件
func CasbinMiddleWare(c *gin.Context) {
var userName string
userName = c.GetHeader("userName")
if userName == "" {
fmt.Println("headers invalid")
c.JSON(200, gin.H{
"code": 401,
"message": "Unauthorized",
"data": "",
})
c.Abort()
return
}
// 请求的path
p := c.Request.URL.Path
// 请求的方法
m := c.Request.Method
// 这里认证
res,err := Enforcer.EnforceSafe(userName,p,m)
// 这个 HasPermissionForUser 跟上面的有什么区别
// EnforceSafe 会验证角色的相关的权限
// 而 HasPermissionForUser 只验证用户是否有权限
//res = Enforcer.HasPermissionForUser(userName,p,m)
if err != nil {
fmt.Println("no permission ")
fmt.Println(err)
c.JSON(200, gin.H{
"code": 401,
"message": "Unauthorized",
"data": "",
})
c.Abort()
return
}
if !res {
fmt.Println("permission check failed")
c.JSON(200, gin.H{
"code": 401,
"message": "Unauthorized",
"data": "",
})
c.Abort()
return
}
c.Next()
}

程序运行后数据库数据为

p 代表的是策略 admin 角色可以使用GET 访问 /api/v2/ping

g 代表的是角色 test 用户在root 角色中

tom 在admin 角色中

所以在测试时请求头

userName = root 有正常响应 (这里不会到数据库验证,策略最后一条)

userName = tom 正常响应 (tom 有admin 角色 , 所以验证通过)

userName = role_admin 正常响应 (参考这里:https://casbin.org/docs/zh-CN/rbac , 正常情况下用户名和角色名称不应该一样)

userName = *** 都无法通过认证

########

最后, 一般的后台开发不会这样设计, 后面继续学习,理解 Casbin 工作原理,为以后开发打下基础;

Casbin + Gin + Gorm 学习探索的更多相关文章

  1. [开源]Gin + GORM + Casbin+vue-element-admin 实现权限管理系统(golang)

    简析 基于 Gin + GORM + Casbin + vue-element-admin 实现的权限管理系统. 基于Casbin 实现RBAC权限管理. 前端实现: vue-element-admi ...

  2. 基于Gin+Gorm框架搭建MVC模式的Go语言后端系统

    文/朱季谦 环境准备:安装Gin与Gorm 本文搭建准备环境:Gin+Gorm+MySql. Gin是Go语言的一套WEB框架,在学习一种陌生语言的陌生框架,最好的方式,就是用我们熟悉的思维去学.作为 ...

  3. App自动化测试框架学习探索--从零开始设计

    App自动化测试框架学习探索--从零开始设计---持续更新中,敬请关注 1 批量执行app自动化测试使用多线程设计思路: 1)并发级别选择用methods 2)采用@Test多线程,数据提供类dp单线 ...

  4. 使用go, gin, gorm编写一个简单的curd的api接口

    go 是一门非常灵活的语言,既具有静态语言的高性能,又有动态语言的开发速度快的优点,语法也比较简单,下面是通过简单的代码实现了一个简单的增删改查 api 接口 hello world 常规版 新建 d ...

  5. Go orm框架gorm学习

    之前咱们学习过原生的Go连接MYSQL的方法,使用Go自带的"database/sql"数据库连接api,"github.com/go-sql-driver/mysql& ...

  6. [Golang] Gin框架学习笔记

    0x0 Gin简介 1.Gin 是什么? Gin 是一个用 Go (Golang) 编写的 HTTP web 框架. 它是一个类似于 martini 但拥有更好性能的 API 框架, 由于 httpr ...

  7. Golang gin框架学习

    今天开始学习gin框架,在Github上找的示例的go-gin-example, 进度 日期 进展 疑惑 进展 1.30 下拉代码,初步了解gin的介绍.搭建 .mod文件 module原理.使用方法 ...

  8. gin+gorm 用户服务

    package main import ( "fmt" "github.com/gin-gonic/gin" "github.com/jinzhu/g ...

  9. Android学习探索之Java 8 在Android 开发中的应用

    前言: Java 8推出已经将近2年多了,引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时减化了各种设计模式的实现方式,是Java有史以来最重要的更新.但是Android上, ...

随机推荐

  1. React Color使用

    需求 - 要在react项目中实现颜色获取器功能 解决方案 - 使用react-color 依赖 - git地址:https://github.com/casesandberg/react-color ...

  2. 分布式NoSQL数据库MongoDB初体验-v5.0.5

    概述 定义 MongoDB官网 https://www.mongodb.com/ 社区版最新版本5.0,其中5.2版本很快也要面世了 MongoDB GitHub源码 https://github.c ...

  3. 使用docker-compose一起安装kafka(zookeeper)

    要先安装docker-compose Linux安装docker-compose 参考:https://www.cnblogs.com/pxblog/p/15049362.html 创建docker- ...

  4. 1301 - Monitoring Processes

    1301 - Monitoring Processes    PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit:  ...

  5. 「Codeforces 724F」Uniformly Branched Trees

    题目大意 如果两棵树可以通过重标号后变为完全相同,那么它们就是同构的. 将中间节点定义为度数大于 \(1\) 的节点.计算由 \(n\) 个节点,其中所有的中间节点度数都为 \(d\) 的互不同构的树 ...

  6. vue 把字符串的所有=替换成&&&的方法

    //把字符串中所有=换成&&& let reg=new RegExp('=','g')//g代表全部 let newMsg=JSON.stringify(msg).replac ...

  7. 基于Spring MVC + Spring + MyBatis的【医院就诊挂号系统】

    资源下载:https://download.csdn.net/download/weixin_44893902/21727306 一.语言和环境 1.实现语言: JAVA语言. 2.环境要求: MyE ...

  8. javaScript系列 [43]-TS、Class and ES5

    本文讨论Typescript中的Class同ES5构造函数的对应关系,涉及TypeScript的诸多语法.构造函数.面向对象以及原型对象等相关知识点细节,本文只简单对比并不进行深入展开. TypeSc ...

  9. Drools的Eclipse_IDEA插件安装

    1.说明 Drools使用时不是必须依赖插件的, 只是在安装了相应的插件之后, 在开发工具中能识别到对应的drools文件, 能够进行一些智能提示. 以及使用插件提供的便捷功能. 2.Eclipse插 ...

  10. JZOJ 3296 Luogu P3296 [SDOI2013]刺客信条

    前言 做法来自:@pzrpzr ,写一下!Orz pzr! 题目大意 \(n\) 个点的无根树,每个点有两个 \(0/1\) 权值,合适地安排节点在同构树中的顺序,使得前后对应的权值不同节点个数最小, ...