1.概述
1.1 Casbin描述
Casbin 是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。
1.2 Casbin 是什么?
Casbin 可以:
- 支持自定义请求的格式,默认的请求格式为{subject, object, action}。
- 具有访问控制模型model和策略policy两个核心概念。
- 支持RBAC中的多层角色继承,不止主体可以有角色,资源也可以具有角色。
- 支持内置的超级用户 例如:root 或 administrator。超级用户可以执行任何操作而无需显式的权限声明。
- 支持多种内置的操作符,如 keyMatch,方便对路径式的资源进行管理,如 /foo/bar 可以映射到 /foo*
Casbin 不能:
- 身份认证 authentication(即验证用户的用户名和密码),Casbin 只负责访问控制。应该有其他专门的组件负责身份认证,然后由 Casbin 进行访问控制,二者是相互配合的关系。
- 管理用户列表或角色列表。 Casbin 认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是 Casbin 的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC方案中用户和角色之间的映射关系。
1.3 Casbin 支持以下编程语言:
| | | |
可用于生产环境 | 可用于生产环境 | 可用于生产环境 | 可用于生产环境 |
| | | |
可用于生产环境 | 可用于生产环境 | 可用于生产环境 | 可用于生产环境 |
1.4 在不同语言中支持的特性
特性 | Go | Java | Node.js | PHP | Python | C# | Delphi | Rust | C++ | Lua | Dart | Elixir |
ACL | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
RBAC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
ABAC (attribute) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
其他等等 |
官网测试数据
1.5 使用的企业
1.6 学习地址
集成casbin-spring-boot-starter地址:GitHub - jcasbin/casbin-spring-boot-starter: Casbin Spring Boot Starter
2.casbin使用
2.1引入java pom文件:
<dependency>
<groupId>org.casbin</groupId>
<artifactId>casbin-spring-boot-starter</artifactId>
<version> 0.1.2 </version>
</dependency>
2.2 引入校验规则
RBAC 规则,其他规则可以看官网git地址案例
model.config文件
# 请求定义 例如 admin, api/bios/user/detail, post
[request_definition]
r = sub, obj, act
# 策略定义 例如 admin, api/bios/user/detail, get
[policy_definition]
p = sub, obj, act
# 角色定义 色继承关系的前项和后项,
# 例如 g r:test, r:root 代表用户拥有两个角色
[role_definition]
g = _, _
# 策略的结果,一般是固定的。 p.eft 代表决策结果, 意思就是:如果存在一个匹配的策略规则就通过。
[policy_effect]
e = some(where (p.eft == allow))
# 请求和策略的匹配规则
# g(r.sub, p.sub) 代表 用户下的角色匹配, r.obj == p.obj 代表对象一致, r.act == p.act 代表action一致
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
2.3 添加配置文件,
application.yml
casbin:
#是否开启Casbin,默认开启
enableCasbin: true
#是否使用线程同步的Enforcer,默认false
useSyncedEnforcer: false
#是否开启策略自动保存,如适配器支持该功能,默认开启
autoSave: true
#存储类型[file,jdbc],目前支持的jdbc数据库[mysql(mariadb),h2,oracle,postgresql,db2]
#欢迎编写并提交您所使用的jdbc适配器,参见:org.casbin.adapter.OracleAdapter
#jdbc适配器将主动寻找您在spring.datasource配置的数据源信息
#默认使用jdbc,并使用内置h2数据库进行内存存储
storeType: jdbc
#当使用jdbc时,定制化数据库表名,默认表名是casbin_rule
tableName: casbin_rule
#数据源初始化策略[create(自动创建数据表,如已创建则不再进行初始化),never(始终不进行初始化)]
initializeSchema: create
#本地模型配置文件地址,约定默认读取位置:classpath:casbin/model.conf
model: classpath:casbin/model.conf
#如默认位置未找到模型配置文件,且casbin.model未正确设置,则使用内置默认rbac模型,默认生效
useDefaultModelIfModelNotSetting: true
#本地策略配置文件地址,约定默认读取位置:classpath:casbin/policy.csv
#如默认位置未找到配置文件,将会抛出异常
#该配置项仅在casbin.storeType设定为file时生效
policy: classpath:casbin/policy.csv
#是否开启CasbinWatcher机制,默认不开启
#如开启该机制,则casbin.storeType必须为jdbc,否则该配置无效
enableWatcher: false
#CasbinWatcher通知方式,默认使用Redis进行通知同步,暂时仅支持Redis
#开启Watcher后需手动添加spring-boot-starter-data-redis依赖
watcherType: redis
#异常抛出时机控制
exception:
启动后系统自动创建持久化表。
2.4 插入创建RBAC权限
用户角色关系: u:11 r:test
角色权限关系: r:test /api/test1
2.5 代码使用:
public class CasbinPolicyManager {
@Autowired
private Enforcer enforcer;
/**
* 规则权限校验
*
* @param userId 请求对象
* @param url 数据
* @return boolean
*/
public Boolean enforceUserUrl(Long userId, String url, String type) {
return enforcer.enforce("u:11", "api/test1", "get");
}
/**
* 为用户新增角色
*
* @param userId
* @param roleIds
*/
public void addUserRole(Long userId, Set<Long> roleIds) {
enforcer.addRoleForUser(userSubject(userId), roleSubject(roleId));
}
/**
* 为角色新增权限
*
* @param userId
* @param roleIds
*/
public void addRolePermissionPolicy(Long roleId, String url, String type) {
enforcer.addPolicy(Lists.newArrayList(roleSubject(roleId), url, type));
}
}
3.casbin分析
3.1 jcasbin架构图
3.2 jcasbinn内部流程图
省略,详细流程见第四章
3.3 落地业务流程图
4 功能流程分析
4.1启动数据初始化
CasbinAutoConfiguration
4.2资源权限校验匹配
CoreEnforcer#enforce
Aviator是一个高效,轻量级的表达式引擎。Aviator 的基本过程是将表达式直接翻译成对应的 java 字节码执行,整个过程最多扫两趟(开启执行优先模式,如果是编译优先模式下就一趟),这样就保证了它的性能超越绝大部分解释性的表达式引擎,测试也证明如此。
- 编译型规则表达式引擎:预先编译成可执行对象,运行时多次执行;
- 解释型规则表达式引擎:不需要预先进行编译,在运行时,要先进行解释再运行
java实例:
Expression expression = aviatorEval.compile(expString, true);
Object result = expression.execute(parameters);
更多了解,官网:1. 介绍 · 语雀
4.3 资源权限校验新增
4.4资源权限更新
目前jdbcAdapter的更新走 remove , insert
1:mysql更新代价比较大,走insert效率比较高
2:集合进行全量删除 +全量插入 > 集合遍历 + 增量更新 + 增量删除
bd更新
remove + insert
// 1.缓存更新
注意:禁止直接更新数据库,因为缓存没有更新,会有缓存,db不一致问题
可以通过接口更新资源信息
4.功能性能优化
4.1 高访量
单个Casbin实例每秒就能收到10000条请求。 在这种情况下,仅靠一个Casbin实例通常难以处理完所有请求。 现在有两种解决方案:
- 运用多线程来运行多个Casbin实例,这样以来您就可以充分利用机器中的所有内核。 详情请参阅:多线程
- 将Casbin实例部署到机器集群(多台机器)。 使用Watcher来确保所有Casbin实例运行一致。 详情请参阅: Watcher。
4.2 大量的策略规则数据
在云或多租户环境中,可能需要数百万条策略规则。 每次执行请求甚至是在最初期加载策略规则的速度非常缓慢。 这类事件通常可以通过以下几种方式缓解:
1. 精致的模型和策略将抽象每个用户/租户的重复逻辑,
2.通过共享让Casbin 的执行者只需要加载一套小套策略规则,详情请参阅 :策略子集加载 。
3.以授予RBAC角色权限,取代直接授予用户权限。 Casbin的RBAC是通过角色继承树来实现的(作为缓存)。 因此授予类似Alice这样的用户权限,Casbin只使用O(1) 时间查询RBAC树来获取角色用户关系并执行操作。 如果您的 g 规则不会经常改变,那么RBAC 树将不需要进行更新。