跳转至主要内容

Casbin 与 CASL 对比

CASL 和 Casbin 是 JavaScript 开发者最常比较的两个授权库。 CASL 为 JavaScript 和 TypeScript 编写,在代码中定义权限。 Casbin 把权限以模型和策略规则的形式放在代码之外,同一套规则可以在 Node.js、浏览器和其他语言中运行。

总结​

CasbinCASL
切换语言Node.js 和浏览器,以及 Go、Java、Python、.NET、PHP、Rust、C++ 等JavaScript 和 TypeScript
规则写法一个模型文件加上按行写的策略规则在代码中调用 can 和 cannot,或使用 JSON 格式的规则对象
典型规则p, editor, article, writecan('update', 'Article', { authorId: user.id })
角色内置:角色分配、层级、按租户的角色需要在自己的代码中把角色映射到 ability
规则存储数据库适配器(Sequelize、TypeORM、Prisma、Mongoose 等)需要自己存储和加载规则
前端casbin.js 从后端接收用户的权限提供 React、Vue 和 Angular 的包
数据库查询过滤通过策略和你自己的查询实现提供把条件转换为 Prisma 或 Mongoose 查询的辅助工具
治理与许可证Apache 软件基金会(孵化中),Apache-2.0社区项目,MIT

规则写在代码中,还是作为数据​

CASL 的 ability 在代码中为当前用户构建:

import { AbilityBuilder, createMongoAbility } from "@casl/ability";

function defineAbilityFor(user) {
const { can, build } = new AbilityBuilder(createMongoAbility);
can("read", "Article");
if (user.role === "editor") {
can("update", "Article", { authorId: user.id });
}
return build();
}

这种写法易读,在 TypeScript 中类型安全,规则固定且由开发者掌握时很方便。要改变谁能做什么,就得修改并重新部署代码,除非你自己为规则对象做一套存储。

Casbin 把这两部分分开。模型描述规则的结构,只需写一次:

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

规则是数据:

p, reader, article, read
p, editor, article, update
g, alice, editor

管理员可以通过 Management API 在运行时添加角色或权限,改动由 适配器 保存到你的数据库。“编辑只能修改自己的文章”这类所有权规则用 ABAC 写在匹配器中:r.sub == r.obj.authorId。

前端​

CASL 在浏览器端很强。它的 React、Vue 和 Angular 包让显示或隐藏按钮变得简单,同一个 ability 对象可以在前后端共用。

使用 Casbin 时,服务器始终是唯一可信来源。它把当前用户的权限发送到浏览器,由 casbin.js 为界面组件回答 can 判断。前端永远不会拿到其他用户的规则。

多种语言​

CASL 只覆盖 JavaScript。如果你的后端有一部分用 Go、Java 或 Python 编写,这些服务需要另一个授权库和另一份规则。

Casbin 的模型和策略与语言无关。 Node.js API、Go worker 和 Python 服务可以从同一个数据库加载同一份策略,得出相同的判定。

如何选择​

如果你的技术栈全是 JavaScript 或 TypeScript,权限由开发者定义且很少在运行时变化,并且想和 UI 框架以及 Prisma 或 Mongoose 查询紧密集成,选 CASL。

如果由管理员在运行时管理角色和权限,需要开箱即用的角色层级或多租户角色,规则应该放在数据库中,或者多个不同语言的服务必须执行同一套策略,选 Casbin。

试用 Casbin​

跟着 Node.js 和 Express 教程 操作,或在 在线编辑器 中测试模型和策略。

另见 对比概览。

Comments are powered by giscus and GitHub Discussions. They load from giscus.app and GitHub only after you click the button below.