casbin-权限管理
概要
权限管理几乎是每个系统或者服务都会直接或者间接涉及的部分. 权限管理保障了资源(大部分时候就是数据)的安全, 权限管理一般都是和业务强关联, 每当有新的业务或者业务变化时, 不能将精力完全放在业务实现上, 权限的调整往往耗费大量的精力.
其实, 权限的本质没有那么复杂, 只是对访问的控制而已, 有一套完善的访问控制接口, 再加上简单的权限模型. 权限模型之所以能够简单, 就是因为权限管理本身并不复杂, 只是在和具体业务结合时, 出现了各种各样的访问控制场景, 才显得复杂.
PERM 模型
PERM(Policy, Effect, Request, Matchers)模型很简单, 但是反映了权限的本质 – 访问控制
- Policy: 定义权限的规则
- Effect: 定义组合了多个 Policy 之后的结果, allow/deny
- Request: 访问请求, 也就是谁想操作什么
- Matcher: 判断 Request 是否满足 Policy

casbin 权限库
casbin 使用了 PERM 模型来表达权限, 并且提供了简单直接的 API.
核心概念
model file
用来定义具体的权限模型, 目前支持的模型基本覆盖了常见的所有场景:
- ACL
- ACL with superuser
- ACL without users
- ACL without resources
- RBAC
- RBAC with resource roles
- RBAC with domains/tenants
- ABAC
- ……
model file 定义语法
casbin 是基于 PERM 的, 所有 model file 中主要就是定义 PERM 4 个部分.
Request definition
[request_definition]
r = sub, obj, act
分别表示 request 中的
- accessing entity (Subject)
- accessed resource (Object)
- the access method (Action)
Policy definition
[policy_definition]
p = sub, obj, act
p2 = sub, act
定义的每一行称为 policy rule, p, p2 是 policy rule 的名字. p2 定义的是 sub 所有的资源都能执行 act
Policy effect
[policy_effect]
e = some(where (p.eft == allow))
上面表示有任意一条 policy rule 满足, 则最终结果为 allow
Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
定义了 request 和 policy 匹配的方式, p.eft 是 allow 还是 deny, 就是基于此来决定的
Role
[role_definition]
g = _, _
g2 = _, _
g3 = _, _, _
g, g2, g3 表示不同的 RBAC 体系, _, _ 表示用户和角色 _, _, _ 表示用户, 角色, 域(也就是租户)
policy file
定义具体的策略, 权限的检查就是基于定义的 model file 和 policy file 来完成的.
相对于 model file 定义规则, policy file 中定义的就是具体的内容.
RBAC 示例
定义 model file
[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
定义 policy file
p, superAdmin, project, read
p, superAdmin, project, write
p, admin, project, read
p, admin, project, write
p, admin, asse, read
p, admin, asse, write
p, zhuangjia, project, write
p, zhuangjia, asse, write
p, shangshang, project, read
p, shangshang, asse, read
g, quyuan, admin
g, wenyin, zhuangjia
测试代码
package rbac
import (
"fmt"
"log"
"github.com/casbin/casbin"
)
func TestRBAC() {
e := casbin.NewEnforcer("rbac/rbac.conf", "rbac/rbac.csv")
fmt.Printf("RBAC test start\n") // output for debug
// superAdmin
if e.Enforce("superAdmin", "project", "read") {
log.Println("superAdmin can read project")
} else {
log.Fatal("ERROR: superAdmin can not read project")
}
if e.Enforce("superAdmin", "project", "write") {
log.Println("superAdmin can write project")
} else {
log.Fatal("ERROR: superAdmin can not write project")
}
// admin
if e.Enforce("quyuan", "project", "read") {
log.Println("quyuan can read project")
} else {
log.Fatal("ERROR: quyuan can not read project")
}
if e.Enforce("quyuan", "project", "write") {
log.Println("quyuan can write project")
} else {
log.Fatal("ERROR: quyuan can not write project")
}
if e.Enforce("quyuan", "asse", "read") {
log.Println("quyuan can read asse")
} else {
log.Fatal("ERROR: quyuan can not read asse")
}
if e.Enforce("quyuan", "asse", "write") {
log.Println("quyuan can write asse")
} else {
log.Fatal("ERROR: quyuan can not write asse")
}
// zhuangjia
if e.Enforce("wenyin", "project", "read") {
log.Fatal("ERROR: wenyin can read project")
} else {
log.Println("wenyin can not read project")
}
if e.Enforce("wenyin", "project", "write") {
log.Println("wenyin can write project")
} else {
log.Fatal("ERROR: wenyin can not write project")
}
if e.Enforce("wenyin", "asse", "read") {
log.Fatal("ERROR: wenyin can read asse")
} else {
log.Println("wenyin can not read asse")
}
if e.Enforce("wenyin", "asse", "write") {
log.Println("wenyin can write asse")
} else {
log.Fatal("ERROR: wenyin can not write asse")
}
// shangshang
if e.Enforce("shangshang", "project", "read") {
log.Println("shangshang can read project")
} else {
log.Fatal("ERROR: shangshang can not read project")
}
if e.Enforce("shangshang", "project", "write") {
log.Fatal("ERROR: shangshang can write project")
} else {
log.Println("shangshang can not write project")
}
if e.Enforce("shangshang", "asse", "read") {
log.Println("shangshang can read asse")
} else {
log.Fatal("ERROR: shangshang can not read asse")
}
if e.Enforce("shangshang", "asse", "write") {
log.Fatal("ERROR: shangshang can write asse")
} else {
log.Println("shangshang can not write asse")
}
}
多租户示例
定义 model file
[request_definition]
r = sub, dom, obj, act
[policy_definition]
p = sub, dom, obj, act
[role_definition]
g = _, _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
定义 policy file
p, superAdmin, gy, project, read
p, superAdmin, gy, project, write
p, superAdmin, jn, project, read
p, superAdmin, jn, project, write
p, admin, gy, project, read
p, admin, gy, project, write
p, admin, jn, asse, read
p, admin, jn, asse, write
p, zhuangjia, jn, project, write
p, zhuangjia, gy, asse, write
g, quyuan, admin, gy
g, quyuan, admin, jn
g, wenyin, zhuangjia, gy
g, shangshang, zhuangjia, jn
测试代码
package tenants
import (
"fmt"
"log"
"github.com/casbin/casbin"
)
// TestTenants test tenants
func TestTenants() {
e := casbin.NewEnforcer("tenants/tenants.conf", "tenants/tenants.csv")
fmt.Printf("RBAC TENANTS test start\n") // output for debug
// superAdmin
if e.Enforce("superAdmin", "gy", "project", "read") {
log.Println("superAdmin can read project in gy")
} else {
log.Fatal("ERROR: superAdmin can not read project in gy")
}
if e.Enforce("superAdmin", "gy", "project", "write") {
log.Println("superAdmin can write project in gy")
} else {
log.Fatal("ERROR: superAdmin can not write project in gy")
}
if e.Enforce("superAdmin", "jn", "project", "read") {
log.Println("superAdmin can read project in jn")
} else {
log.Fatal("ERROR: superAdmin can not read project in jn")
}
if e.Enforce("superAdmin", "jn", "project", "write") {
log.Println("superAdmin can write project in jn")
} else {
log.Fatal("ERROR: superAdmin can not write project in jn")
}
// admin
if e.Enforce("quyuan", "gy", "project", "read") {
log.Println("quyuan can read project in gy")
} else {
log.Fatal("ERROR: quyuan can not read project in gy")
}
if e.Enforce("quyuan", "gy", "project", "write") {
log.Println("quyuan can write project in gy")
} else {
log.Fatal("ERROR: quyuan can not write project in gy")
}
if e.Enforce("quyuan", "jn", "project", "read") {
log.Fatal("ERROR: quyuan can read project in jn")
} else {
log.Println("quyuan can not read project in jn")
}
if e.Enforce("quyuan", "jn", "project", "write") {
log.Fatal("ERROR: quyuan can write project in jn")
} else {
log.Println("quyuan can not write project in jn")
}
if e.Enforce("quyuan", "gy", "asse", "read") {
log.Fatal("ERROR: quyuan can read asse in gy")
} else {
log.Println("quyuan can not read asse in gy")
}
if e.Enforce("quyuan", "gy", "asse", "write") {
log.Fatal("ERROR: quyuan can write asse in gy")
} else {
log.Println("quyuan can not write asse in gy")
}
if e.Enforce("quyuan", "jn", "asse", "read") {
log.Println("quyuan can read asse in jn")
} else {
log.Fatal("ERROR: quyuan can not read asse in jn")
}
if e.Enforce("quyuan", "jn", "asse", "write") {
log.Println("quyuan can write asse in jn")
} else {
log.Fatal("ERROR: quyuan can not write asse in jn")
}
// wenyin
if e.Enforce("wenyin", "gy", "asse", "write") {
log.Println("wenyin can write asse in gy")
} else {
log.Fatal("ERROR: wenyin can not write asse in gy")
}
if e.Enforce("wenyin", "jn", "asse", "write") {
log.Fatal("ERROR: wenyin can write asse in jn")
} else {
log.Println("wenyin can not write asse in jn")
}
// shangshang
if e.Enforce("shangshang", "jn", "project", "write") {
log.Println("shangshang can write project in jn")
} else {
log.Fatal("ERROR: shangshang can not write project in jn")
}
if e.Enforce("shangshang", "gy", "project", "write") {
log.Fatal("ERROR: shangshang can write project in gy")
} else {
log.Println("shangshang can not write project in gy")
}
}
总结
casbin 权限管理库比较简单, 易上手, 但是它的功能却不简单, 支持了目前主流的所有权限管理场景. 在使用上, model file 和 poclicy file 的定义也简单明了, 抽象出了权限管理最本质的东西.
将具体业务中的权限要求映射到 casbin 中 model file, 就可以借助 casbin 的 API, 快速的实现权限管理.
casbin-权限管理的更多相关文章
- Casbin权限模型
权限框架casbin1.概述Casbin是一个强大的.高效的开源访问控制框架,其权限管理机制支持多种访问控制模型. Casbin支持以下编程语言: Casbin可以做到:支持自定义请求的格式,默认的请 ...
- Android权限管理之RxPermission解决Android 6.0 适配问题
前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...
- Android权限管理之Android 6.0运行时权限及解决办法
前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...
- Android权限管理之Permission权限机制及使用
前言: 最近突然喜欢上一句诗:"宠辱不惊,看庭前花开花落:去留无意,望天空云卷云舒." 哈哈~,这个和今天的主题无关,最近只要不学习总觉得生活中少了点什么,所以想着围绕着最近面试过 ...
- SpringMVC+Shiro权限管理【转】
1.权限的简单描述 2.实例表结构及内容及POJO 3.Shiro-pom.xml 4.Shiro-web.xml 5.Shiro-MyShiro-权限认证,登录认证层 6.Shiro-applica ...
- Android6.0运行时权限管理
自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有的权限而导致的无法安装 ...
- Oracle 表空间和用户权限管理
一. 表空间 Oracle数据库包含逻辑结构和物理结构. 数据库的物理结构指的是构成数据库的一组操作系统文件. 数据库的逻辑结构是指描述数据组织方式的一组逻辑概念以及它们之间的关系. 表空间是数据库逻 ...
- [Django]用户权限学习系列之权限管理界面实现
本系列前三章: http://www.cnblogs.com/CQ-LQJ/p/5604331.htmlPermission权限基本操作指令 http://www.cnblogs.com/CQ-LQJ ...
- [Django]用户权限学习系列之设计自有权限管理系统设计思路
若在阅读本片文章遇到权限操作问题,请查看本系列的前两章! http://www.cnblogs.com/CQ-LQJ/p/5609690.html和http://www.cnblogs.com/CQ- ...
- 我的MYSQL学习心得(十三) 权限管理
我的MYSQL学习心得(十三) 权限管理 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
随机推荐
- SQL Server 2008R2 :远程调用失败 的解决方法(全部方法)
SQL 中远程调用失败的原因 1.服务里面的启动权限未能启动,修改sql对应的服务进程权限就可以了 2.是因为VS 和SQL 起冲突了,数据库找不到访问地址导致的.解决的办法很简单,就是卸载掉多余的版 ...
- spring 【二】学习之spring EL
spring EL-spring 表达式语言,支持在xml和注解的形式,类似于JSP的el表达式的形式. 其主要使用@Value注解的结构形式 其主要功能 [1].注入普通字符串 [2].注入操作系统 ...
- WEB框架-Django框架学习-关联管理器(RelatedManager)
一.class RelatedManager "关联管理器"是在一对多或者多对多的关联上下文中使用的管理器.它存在于下面两种情况: 1.一对多 ForeignKey关系的“另一边” ...
- 第二章.python入门
2.1环境的安装 解释器:py2和py3 添加环境变量的作用:便于找到python解释器 开发工具:pycharm 2.2编码 2.2.1编码基础 ascii:只表示英文,8位表示一个元素,pytho ...
- 从Android源码修改cpu信息
cpuinfo 网上的文章都是怎么查看/proc/cpuinfo,一直以为这种东西没法改呢,我还是太天真了./proc/cpuinfo是个文件,只读,想直接写肯定不行的.今天研究了一下,发现它的输出逻 ...
- Dubbo的@Reference和@Service说明
前言 @Reference 用在消费端,表明使用的是服务端的什么服务 @RestController public class RemoteUserController { @Reference(ve ...
- 爬虫框架之Scrapy(二)
递归解析 糗事百科递归解析 在前面的例子里只是爬取了糗事百科热门的第一个页面,但是当我们需要爬取更多的页面时,需要对每个页面的url依次发起请求,然后通过解析的方法进行作者和标题的解析. 我们可以构建 ...
- 批量执行工具PSSH详解
批量执行工具PSSH详解 pssh是一个python编写可以在多台服务器上执行命令的工具,同时支持拷贝文件,是同类工具中很出色的,使用必须在各个服务器上配置好密钥认证访问. 安装pssh包 yum 安 ...
- Linux~学习笔记目录索引
回到占占推荐博客索引 本篇文章是对自己学习Linux及在它的环境下部署工具的一个总结,以方便自己查阅,也给他人一个帮助,本文章同时会不断的更新,欢迎大家订阅! 本目录包括的内容会包括linux基础命令 ...
- JS数组添加删除
栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.原文: https://www.w3cplus.com/j ...