casbin轻量级的基于配置的授权框架

news2024/12/23 18:12:18

简介

Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。

Casbin提供了一个执行者 根据提供给执行者的策略和模型文件验证传入的请求。再根据对应的配置授权策略,验证请求判断释放那些行动。

在 Casbin 中, 访问控制模型被抽象为基于 PERM (Policy, Effect, Request, Matcher) 的一个配置文件。PERM模式由四个基础(策略、效果、请求、匹配)组成,描述了资源与用户之间的关系。通过配置文件对用户授权更方便授权系统的更改和迭代。

Casbin使用配置文件来设置访问控制模式。

工作原理

访问控制模型PERM是casbin的权限机制,通过4个对象Policy, Effect, Request, Matcher描述了资源的关系。

请求

定义请求参数。 基本请求是一个元组对象,至少需要访问实体(Subject)、访问资源(Object) 和访问方式(Action)。

请求是访问携带的对象,携带用户访问权限。

r = sub, obj, act

策略

policy部分的每一行称之为一个策略规则, 每条策略规则通常以形如p, p2的policy type开头。策略定义了匹配模式。不同的模式需要满足不同的匹配规则。

p = sub, obj, act
p2 = sub, act

规则

匹配请求和匹配策略的比较规则,不同的匹配策略比较方式不同。

m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

在策略中定义了p和p2两种匹配模式,匹配规则中定义了请求和p策略的比较规则。

效果

效果是匹配结果的判断。

e = some (where (p.eft == allow))

匹配策略p没有定义匹配结果eft,但是每个匹配规则都会默认存在匹配结果。

这些规则的定义都是casbin支持的访问控制模型。这个模型的名称叫ACL。另外casbin还支持其他很多模型如RBAC,ABAC等。

一个完整的ACL模型如下:

# casbin请求格式
[request_definition]
r = sub, obj, act

# casbin策略模式
[policy_definition]
p = sub, obj, act
p2 = sub, act

# casbin测率匹配结果
[policy_effect]
e = some(where (p.eft == allow))

# casbin率略匹配规则
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

[request_definition]类似定义是声明请求等对象不可缺少。在ACL模型中至少需要访问实体(Subject)、访问资源(Object) 和访问方式(Action)。命名不仅限于sub,obj,act,只要请求和策略和匹配对应即可。

上述的ACL模型表示的含义是定义了sub, obj, act为匹配对象的p策略;定义请求p需要按照策略的格式携带参数;定义匹配规则m对请求参数匹配请求策略;最好返回匹配结果e。

这些过程都是casbin框架自主完成的,只需要使用casbin提供的接口就可以按规则传入参数并得到匹配结果。但是访问权限控制的这些规则需要定义,因为官方提供了众多规则模型,需要开发者自己选择合适的模型。

规则模型定义子在conf文件中,model.conf:

# casbin请求格式
[request_definition]
r = sub, obj, act

# casbin策略模式
[policy_definition]
p = sub, obj, act
p2 = sub, act

# casbin测率匹配结果
[policy_effect]
e = some(where (p.eft == allow))

# casbin率略匹配规则
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

在这里插入图片描述

策略授权

访问权限控制模型已经定义了,就需要定义具体的用户授权了,该步骤是将实际的用户与匹配规则联系起来。

casbin使用配置来控制访问权限,授权机制使用csv文件。police.csv

p,xiaoxu,data1,read
p,zhangsan,data2,write

上述匹配规则下p模式,xiaoxu用户可以访问,data1,访问限制为read;zhangsan用户可以访问data2,访问权限为write。

案例

简单案例
在这里插入图片描述

主函数如下:

package main

import (
	"fmt"
	"github.com/casbin/casbin/v2"
)

func main() {
	e, err := casbin.NewEnforcer("model.conf", "policy.csv")
	if err != nil {
		println(err)
		return
	}
	enforce, err := e.Enforce("xiaoxu", "data1", "read")
	if err != nil {
		println(err)
	}
	fmt.Println("访问权限结果", enforce)

}

casbin.NewEnforcer()方法加载模型和授权策略,返回casbin.Enforcer对象,改对象的e.Enforce方法传入用户的请求,返回是否有访问权限。

main函数的执行结果为true,表示"xiaoxu", “data1”, "read"满足匹配策略有访问权限。
在这里插入图片描述

如果将用户名修改为在policy.csv没有相应的配置,就会返回false表示没有权限访问。

gin框架中间件整合casbin

package main

import (
	"github.com/casbin/casbin/v2"
	"github.com/gin-gonic/gin"
)

func main() {
	/*
		e, err := casbin.NewEnforcer("model.conf", "policy.csv")
		if err != nil {
			println(err)
			return
		}
		enforce, err := e.Enforce("xiaoxu1", "data1", "read")
		if err != nil {
			println(err)
		}
		fmt.Println("访问权限结果", enforce)
	*/
	
	//gin路由

	engine := gin.Default()
	engine.GET("/data1", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data1")
	})
	engine.GET("/data2", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data2")
	})
	engine.GET("/data3", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data3")
	})

	engine.Run("127.0.0.1:8080")
}

//定义权限中间件

func casbinAuth() gin.HandlerFunc {
	return func(context *gin.Context) {
		var req CasbinRequest
		context.ShouldBindJSON(&req)
		if casBin(req.Sub, req.Obj, req.Act) {
			context.Next()
		} else {
			context.Next()
			context.String(503, "没有权限访问!")
		}
	}
}

//定义casbin模型

func casBin(sub, obj, act string) bool {
	e, err := casbin.NewEnforcer("model.conf", "policy.csv")
	if err != nil {
		println(err)
		return false
	}
	enforce, err := e.Enforce(sub, obj, act)
	if err != nil {
		println(err)
		return false
	}
	return enforce
}

type CasbinRequest struct {
	Sub  string `json:"sub"`
	Obj  string `json:"obj"`
	Act  string `json:"act"`
	Data string `json:"data"`
}

请添加图片描述

通过gin的中间价调用casbin的方法判断是否有访问权限。

将权限配置做如下修改:

p,xiaoxu,data1,read
p,xiaoxu,data1,write

p,xiaoxu,data2,write

p,xiaoxu,data3,read


p,zhangsan,data2,read
p,zhangsan,data3,read

请添加图片描述

在实际项目中policy.csv的配置显然是不合适的,在web项目中,权限对应的是api接口,那么就需要与当前地址匹配,判断用户权限。

在上面权限验证的过程中忽略了一个问题,就是casbin.NewEnforcer是验证式策略,只要plicy.csv中配置存在就会返回true,那么将Sub看作用户,Obj看作资源,Act看作接口即可实现权限配置。如下重构的代码:

package main

import (
	"github.com/casbin/casbin/v2"
	"github.com/gin-gonic/gin"
	"strings"
)

func main() {
	engine := gin.Default()
	engine.GET("/data1/list", casbinAuth(), func(context *gin.Context) {
		context.String(200, " data1 list ...")
	})
	engine.GET("/data1/add", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data1 add ...")
	})
	engine.GET("/data1/delete", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data1 delete  ...")
	})
	engine.GET("/data1/update", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data1 update ...")
	})
	engine.GET("/data2/list", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data2 list  ...")
	})
	engine.GET("/data2/add", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data2 add ...")
	})
	engine.GET("/data2/delete", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data2 delete  ...")
	})
	engine.GET("/data2/update", casbinAuth(), func(context *gin.Context) {
		context.String(200, "data2 update ...")
	})

	engine.Run("127.0.0.1:8080")
}

//定义权限中间件

func casbinAuth() gin.HandlerFunc {
	return func(context *gin.Context) {
		var req Username
		context.ShouldBindJSON(&req)
		//获取路径地址
		path := context.FullPath()
		split := strings.Split(path, "/")
		//fmt.Println(split)
		sub := req.Username
		obj := split[1] //请求的资源
		act := split[2] //请求资源的权限
		//
		if casBin(sub, obj, act) {
			context.Next()
		} else {
			context.Next()
			context.String(503, "没有权限访问!")
		}
	}
}

//定义casbin模型

func casBin(sub, obj, act string) bool {
	e, err := casbin.NewEnforcer("model.conf", "policy.csv")
	if err != nil {
		println(err)
		return false
	}
	enforce, err := e.Enforce(sub, obj, act)
	if err != nil {
		println(err)
		return false
	}
	return enforce
}

type Username struct {
	Username string `json:"username"`
}

policy.csv如下:

p,xiaoxu,data1,list
p,xiaoxu,data1,add
p,xiaoxu,data1,delete
p,xiaoxu,data1,update


p,zhangsan,data1,list
p,zhangsan,data1,add

p,list,data2,list
p,list,data2,add
p,list,data2,delete
p,list,data2,update

data1类似的配置是配置资源,add等表示增删改查的行动,也表示uil地址。上述配置赋予了xiaoxu的增删改查的全部权限,zhansan用户只有查和增,list有data2资源的全部权限。

重构代码如下:

请添加图片描述

用户权限的配置不仅限于policy.csv文件配置,也可以使用数据库。

新建Casbin enforcer的时候 你必须提供一个 Model 和一个 Adapter。model就是model.conf,Adapter默认是 FileAdapter。如果要是hi用数据库就需要更改适配器。

更改适配器官方文档

casbin官方文档

教程文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/503296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

由于找不到vcomp140.dll无法继续执行代码,解决方法全攻略

如何解决找不到vcomp140.dll错误?在使用某些软件或者游戏的时候,你可能会遇到下面的错误提示:“由于找不到vcomp140.dll,无法继续执行代码”。这个错误提示通常表示你的电脑缺少一个或多个DLL文件,而这些文件是软件和游…

「字节跳动测试开发面经」一二三面+hr面+超级全资料+复习资料

​ 说在前面,面试时最好不要虚报工资。本来字节跳动是很想去的,几轮面试也通过了,最后没offer,自己只想到几个原因: 1、虚报工资,比实际高30%; 2、有更好的人选,这个可能性不大&am…

【Linux】软件包管理器 yum和编辑器-vim的基本使用

文章目录 一、yum背景知识1.商业生态2.开源生态3.Linux软件生态本土化 二、yum的基本使用1.什么是软件包2.查看软件包3.安装软件4.卸载软件5.rzsz 三、vim的基本使用1.vim的基本概念2.vim的基本操作3.vim命令模式命令集4.vim末(底)行模式命令集5.操作总结 四、简单vim配置1.vim…

C++学习day--10 条件判断、分支

1、if语句 if 语句的三种形态 形态1&#xff1a;如果。。。那么。。。 #include <iostream> using namespace std; int main( void ) { int salary; cout << " 你月薪多少 ?" ; cin >> salary; if (salary < 20000) { cout <&…

浅谈整除分块

例题一 ∑ i 1 n ⌊ n i ⌋ \sum_{i1}^n \lfloor\frac n i\rfloor\\ i1∑n​⌊in​⌋ 首先很容易想到直接求解&#xff0c;对于较大的数据&#xff0c; O ( n ) O(n) O(n)做法无法通过。 注意到函数 y ⌊ n x ⌋ y\lfloor\dfrac n x\rfloor y⌊xn​⌋的图像如下&#xff1a…

Hive语言

一、Hive的DDL语言&#xff08;数据库、数据表的增删改查操作) 二、Hive的DQL语言&#xff08;数据库查询语言&#xff09; 2.1Hive七子句 聚合函数&#xff1a;count()、sum()、max()、min()、avg()可以单独使用。(缩写&#xff1a;cs mm a) 2.1.1 分区查询与分区裁剪 SELEC…

OpenGL(九)——颜色

目录 一、前言 二、简单光源 三、光照场景 3.1 创建光源 3.2 光源顶点着色器 3.3 光源片段着色器 3.4 物体片段着色器 3.5 光源位置 一、前言 我们看到的物体颜色是通过光照在物体&#xff0c;然后反射到人眼成像&#xff0c;具体而言是物体不能吸收的颜色。如白光照射…

C++学习day--09 字符串比较、运算符

1、项目练习 第 1 节 项目需求、项目实现 项目实现&#xff1a; #include <iostream> #include <Windows.h> #include <string> using namespace std; int main( void ) { string name; string pwd; std::cout << " 请输入账号&am…

GPT-4的免费使用方法分享

目录 方法1&#xff1a;使用Ora.sh的LLM应用 方法2&#xff1a;使用https://steamship.com 方法3&#xff1a;使用https://nat.dev 方法4&#xff1a;http://tdchat.vip 方法5&#xff1a;使用Poe网站或App 方法6&#xff1a;使用 Opencat App 方法7:使用https://Huggin…

uniApp实现公农日历相互转换、公历、农历、阳历、阴历、calendar

文章目录 效果图1、组件1.1、html部分1.2、JavaScript部分1.3、style部分 2、使用组件3、总结 效果图 1、组件 1.1、html部分 <template><view v-if"isCalendar" class"calendar_box"><view v-show"!isTime" class"btn_ca…

Linux服务器使用supervisorctl命令部署Java服务详解

我们公司采用supervisorctl命令运行Java -jar包&#xff0c;觉得还是很方便的&#xff0c;此篇文章教你如何使用supervisorctl从零部署Java服务 安装jdk 首先肯定是下载安装Java的运行环境 jdk 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#jav…

WindowContainer相关类

WindowContainer类   从WindowContainer类的注释中可以看出该类中定义了一些公共的方法和属性给直接持有窗口的自己或者它的孩子使用&#xff0c;像RootWindowContainer、DisplayContent、DisplayArea、DisplayArea.Tokens、TaskDisplayArea、Task、ActivityRecord、WindowTok…

【话题讨论】-浅谈VR与AR

一、引言 随着ICT基础技术的发展&#xff0c;我们现在社会中的基础ict设施已经逐步完善&#xff0c;从而我们的社会也开始出现科幻片中才会有的场景&#xff0c;比如&#xff1a;我们可以构件一个虚拟3D沙盘。 还有我们熟悉的各类智能眼镜&#xff0c;已经进入到千家万户&…

干货 | Mendeley 的基础使用方法

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 当阅读的文献越来越多&#xff0c;如何整理文献就成了一个大问题。文献管理软件则减轻了我们文献整理的负担。目前的文献管理软件使用较多的有Endnote、Notepress、Mendeley、Zotero等。 …

边无际首发ChatIoT:AI大模型从数字世界向物理世界迈进

将大模型的能力带到物理世界&#xff0c;除了微软、谷歌&#xff0c;还有一家中国的创业公司。边无际作为专注于物联网开发平台研发的科技公司&#xff0c;紧跟AI大模型带来的生产力变革&#xff0c;首发ChatIoT&#xff0c;率先将大模型的技术应用于物联网领域。 在微软、谷歌…

【高并发】网络模式

I/O 多路复用 多线程创建 服务器的主进程负责监听客户的连接&#xff0c;一旦与客户端连接完成&#xff0c;accept() 函数就会返回一个「已连接 Socket」&#xff0c;这时就通过 fork() 函数创建一个子进程&#xff0c;实际上就把父进程所有相关的东西都复制一份&#xff0c;…

多层感知器Multi-Layer Perception ,MLP

MLP神经网络的结构和原理 神经网络其实是对生物神经元的模拟和简化&#xff0c;生物神经元由树突、细胞体、轴突等部分组成。 生物神经元具有兴奋和抑制两种状态&#xff0c;当接受的刺激高于一定阈值时&#xff0c;则会进入兴奋状态并将神经冲动由轴突传出&#xff0c;反之则…

nginx配置文件nginx.conf的结构、各个指令(元素)的含义以及用法

nginx配置文件nginx.conf的结构、各个指令&#xff08;元素&#xff09;的含义以及用法 默认的nginx.confnginx.conf配置文件官方解释nginx.conf配置文件中每一条指令或指令快的含义是什么&#xff0c;以及用法&#xff08;使用范围&#xff1a;应该配置在什么地方&#xff09;…

今年的面试难度有点大....

大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;又得准备面试了&#xff0c;不知道从何下手&#xff01; 不论是跳槽涨薪&#xff0c;还是学习提升&#xff01;先给自己定一个小目标&#xff0c;然后再朝着目标去努力就完事儿了&#xff01; 为了帮大家节约时间&a…

Selenium:利用select模块处理下拉框

目录 一、具体问题 二、解决方案 在UI自动化测试中&#xff0c;有时候会遇到页面元素无法定位的问题&#xff0c;包括xpath等方法都无法定位&#xff0c;是因为前端元素被设置为不可见导致。 这篇博客&#xff0c;介绍下如何通过JavaScript修改页面元素属性来定位的方法。。…