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. JS判断是否是苹果系统(ios)和安卓系统(Android)客户端

    通过判断浏览器的userAgent,用正则来判断是否是ios和Android客户端.代码如下: <script type="text/javascript"> var ...

  2. windows10下vscode+cmake编译Qt5代码

    概述 本文演示环境: windows10 cmake version:3.18 qt version: 5.14 vscode version: 1.54.1 本文演示环境基于在线模式, 离线使用VS ...

  3. c(++)变长参数之整形(非字符串类型类似)

    0.序言 变长参数,接触的第一个可变长参数函数是 printf   , 然后是 scanf   .他们的原型如下: printf: _Check_return_opt_ _CRT_STDIO_INLI ...

  4. vc++ 调用winapi调节屏幕亮度(增加win7代码demo)

    1.关于 代码是通过测试的,测试环境: win7 + MFC 为什么要发在这里? 区别于上一篇随笔. MD排版更顺眼 demo 会放到 这里 更正了上一篇随笔中的代码错误 2.头文件 #include ...

  5. 【LeetCode】1464. 数组中两元素的最大乘积 Maximum Product of Two Elements in an Array (Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力 找最大次大 日期 题目地址:https://le ...

  6. 【LeetCode】186. Reverse Words in a String II 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 每个单词单独翻转+总的翻转 日期 题目地址:https ...

  7. SOA 和微服务

    ====>场景 不可能让客户端与6个不同的应用/系统都一一去通信来去完成数据的展示.而是6个应用/系统之间进行彼此通信来完成调用,最后客户端只需要调用一个接口来获取数据即可. SOA架构 SOA ...

  8. WebRTC源码开发(一)MacOS下源码下载、编译及Demo运行

    工作需要测试网络传输算法,逐学习WebRTC源码 工作环境 Mac OS 10.14 Xcode 10.2.1 源码下载 从google(需要[你懂的]) 首先[你懂的] 打开终端,输入curl ww ...

  9. [C++]C++四舍五入保留到n位小数

    #include <sstream> #include <iostream> #include <iomanip> using namespace std; /** ...

  10. 求区间内第一个大于等于x的数的下标

    int tree[4*N]; void build(int o,int l,int r) { if(l==r) {cin>>tree[o];return;} build(ls,l,mid) ...