Casbin

Model

Model语法

Model CONF 至少应包含四个部分: [request_definition], [policy_definition], [policy_effect], [matchers]。

如果 model 使用 RBAC, 还需要添加[role_definition]部分。

Model CONF 文件可以包含注释。注释以 # 开头, # 会注释该行剩余部分。

request定义

[request_definition] 部分用于request的定义,它明确了 e.Enforce(...) 函数中参数的含义。

[request_definition] 
r = sub, obj, act

sub, obj, act 表示经典三元组: 访问实体 (Subject),访问资源 (Object) 和访问方法 (Action)。 但是, 你可以自定义你自己的请求表单, 如果不需要指定特定资源,则可以这样定义 sub、act ,或者如果有两个访问实体, 则为 sub、sub2、obj、act。

Policy定义

[policy_definition] 部分是对policy的定义,以下文的 model 配置为例:

[policy_definition] 
p = sub, obj, act 
p2 = sub, act


policy部分的每一行称之为一个策略规则, 每条策略规则通常以形如p, p2的policy type开头。 如果存在多个policy定义,那么我们会根据前文提到的policy type与具体的某条定义匹配。 上面的policy的绑定关系将会在matcher中使用

策略规则中的元素总被视为字符串

Policy effect定义

[policy_effect] 是策略效果的定义。 它确定如果多项政策规则与请求相符,是否应批准访问请求。

[policy_effect]
 e = some(where (p.eft == allow))


上面的策略效果表示如果有任何匹配的策略规则 允许, 最终效果是 允许 (aka allow-override). p.eft 是策略的效果,它可以 允许 或 否定。 它是可选的,默认值是 允许。 因为我们没有在上面指定它,所以它使用默认值。

如果没有匹配的政策规则为否定, 最终效果是 允许 (别名为拒绝). some 表示:如果存在一个匹配的策略规则。 any 意味着:所有匹配的政策规则(这里不使用)。 策略效果甚至可以与逻辑表达式相关联

[policy_effect] 
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))


这意味着至少有一个匹配的策略规则允许,并且没有匹配的否定的 的策略规则。 因此,允许和拒绝授权都得到支持,拒绝则被推翻。

匹配器

[matchers] 是策略匹配程序的定义。匹配程序是表达式。它定义了如何根据请求评估策略规则。

[matchers] 
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

上述匹配器是最简单的,这意味着请求中的主题、对象和行动应该与政策规则中的匹配。

您可以在匹配器中使用诸如 +, -, *, / 和逻辑操作员,例如 &&, ||, !

效果器

Effect是一个policy rule的结果 Effector 是用于Casbin effector的API

MergeEffects()
MergeEffects将 enforcer 收集的所有匹配结果合并为一项决定。

Effect, explainIndex, 
err = e.MergeEffects(expr, effects, matches, policyIndex, policyLength)
  • Effect 是此函数合并的最后决定(初始参数为 indeterminate)。
  • explainIndex 是 eft 的索引,eft 的值可为 Allow 或者 Deny.(初始值是 -1)
  • err 用于检查effect是否受到支持。
  • expr 是被存储为 string 的policy_effects
  • effects 是 Effect 的数组,其中值可以为Allow, Indeterminate 或者 Deny
  • matchers 是显示结果是否符合策略的数组。
  • policyIndex 是模型中的策略索引。
  • policyLength 是策略的长度。

上面的代码说明了我们如何将参数传递到 MergeEffects 函数,并且该函数将根据 expr 处理效果和匹配。

函数

Matchers函数

你甚至可以在Matcher中指定函数,使它更强大。 你可以使用内置函数,或者指定你自己的函数。 所有的内置函数都需要这样的格式(除了 keyGet 和 keyGet2)

bool function_name(string arg1, string arg2)


它返回arg1是否匹配arg2。

keyGet and keyGet2 将返回匹配通配符的字符串,如果没有匹配返回 ""。

怎样增加自定义函数

首先准备您的函数。 它接受一些参数,然后返回一个布尔类型,然后用 interface{} 类型的接口包装它,最后,在Casbin的执行者(enforcer)中注册这个函数。

基于角色的访问控制

角色定义

[role_definition] 是RBAC角色继承关系的定义。 Casbin 支持 RBAC 系统的多个实例, 例如, 用户可以具有角色及其继承关系, 资源也可以具有角色及其继承关系。 这两个 RBAC 系统不会互相干扰。

此部分是可选的。 如果在模型中不使用 RBAC 角色, 则省略此部分。

[role_definition] 
g = _, _ g2 = _, _


上述角色定义表明, g 是一个 RBAC系统, g2 是另一个 RBAC 系统。 _, _表示角色继承关系的前项和后项,即前项继承后项角色的权限。 一般来讲,如果您需要进行角色和用户的绑定,直接使用g 即可。 当您需要表示角色(或者组)与用户和资源的绑定关系时,可以使用g 和 g2 这样的表现形式
注意

  1. Casbin 只存储用户角色的映射关系。
  2. Cabin 没有验证用户是否是有效的用户,或者角色是一个有效的角色。 这应该通过认证来解决。
  3. RBAC 系统中的用户名称和角色名称不应相同。因为Casbin将用户名和角色识别为字符串, 所以当前语境下Casbin无法得出这个字面量到底指代用户 alice 还是角色 alice。 这时,使用明确的 role_alice ,问题便可迎刃而解。
  4. 假设A具有角色 B,B 具有角色 C,并且 A 有角色 C。 这种传递性在当前版本会造成死循环。

角色层次

Casbin 的 RBAC 支持 RBAC1 的角色层次结构功能,如果 alice具有role1, role1具有role2,则 alice 也将拥有 role2 并继承其权限。

下面是一个称为层次结构级别的概念。 因此, 此示例的层次结构级别为2。 对于Casbin中的内置角色管理器, 可以指定最大层次结构级别。 默认值为10。 这意味着终端用户 alice 只能继承10个级别的角色。

Model存储

与 policy 不同,model 只能加载,不能保存。 因为我们认为 model 不是动态组件,不应该在运行时进行修改,所以我们没有实现一个 API 来将 model 保存到存储中。

从.CONF文件中加载model

 

[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 


接着可以加载模型文件

e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")

Policy存储

从CSV文件载入策略

CSV文件示例

p, alice, data1, read 
p, bob, data2, write 
p, data2_admin, data2, read 
p, data2_admin, data2, write 
g, alice, data2_admin

注意
如果你的文件包含逗号, ,你应该用双引号把它包裹

p, alice, "data1,data2", read --correcy 
p, alice, data1,data2, read --insur ("data1,data2" 应该是一个整体)

如果您的文件包含逗号, 和双引号", 你应该用双引号将字段放在一起, 并将任何嵌入的双引号加倍。

p, alice, data, "r.act in (""get"", ""post"")" --correct 
p, alice, data, "r.act in ("get", "post")" --insur --unction (should use "" to fescape "")

政策子集加载

一些adapter支持过滤策略管理。 这意味着Casbin加载的策略是基于给定过滤器的存储策略的子集。 当解析整个策略成为性能瓶颈时,这将会允许在大型多租户环境中有效地执行策略。

要使用支持的adapter处理过滤后的策略,只需调用 LoadFilteredPolicy 方法。 过滤器参数的有效格式取决于所用的适配器。 为了防止意外数据丢失,当策略已经加载, SavePolicy 方法会被禁用。

API

Enforce API

// 从文件中加载信息 
enforcer, err := casbin.NewEnforcer("./example/model.conf", "./example/policy.csv") 
if err != nil {
    log.Fatalf("error, detail: %s", err) 
} 
ok, err := enforcer.Enforce("alice", "data1", "read")


这段代码从本地文件加载访问控制模型和策略。 函数casbin.NewEnforcer()将返回一个执行者。 它将识别其两个参数为文件路径,并从那里加载文件。 过程中发生的错误被存储在err中。 这段代码使用默认的适配器来加载模型和策略。 当然,你也可以通过使用第三方适配器得到同样的结果。

代码ok, err := enforcer.Enforce("alice", "data1", "read")是为了确认访问权限。 如果alice可以通过read操作访问data1,返回值ok将是true,否则将是false。 在这个例子中,ok的值是true。

EnforceEx API

ok, reason, err := enforcer.EnforceEx("amber", "data1", "read" fmt.Println(ok, reason) 
// true [admin data1 read]


函数EnforceEx()将在返回值reason中返回准确的策略字符串。 在这个例子中,amber是admin的一个角色,所以策略p, admin, data1, read使得这个请求true。 这段代码的输出在注释中。

Casbin准备了很多这样的API。 这些API在基本的功能上增加了一些额外的功能。

  • ok, err := enforcer.EnforceWithMatcher(matcher, request)

        与一个匹配器。

  • ok, reason, err := enforcer.EnforceExWithMatcher(matcher, request)

        EnforceWithMatcher()和EnforceEx()的组合。

  • boolArray, err := enforcer.BatchEnforce(requests)

        对列表执行,然后返回一个数组

管理API

用于策略获取API

  • policy = e.GetPolicy()用于获取策略中的授权规则。
  • filteredPolicy := e.GetFilteredPolicy(0, "alice")用于获取策略中的授权的规则,可以自定义“域过滤器”(field filters)。
  • namedPolicy := e.GetNamedPolicy("p") 用于获取被命名的策略中所有被授权的规则
  • filteredNamedPolicy = e.GetFilteredNamedPolicy("p", 0, "bob")用于获取被命名的策略中所有被授权的规则,可以自定义“域过滤器”(field filters)。
  • groupingPolicy := e.GetGroupingPolicy()用于获取策略中所有任务继承规则。
  • filteredGroupingPolicy := e.GetFilteredGroupingPolicy(0, "alice")用于获取策略中所有任务继承规则,可以自定义“域过滤器”(field filters)。
  • namedGroupingPolicy := e.GetNamedGroupingPolicy("g")用于获取策略中所有任务继承规则。
  • namedGroupingPolicy := e.GetFilteredNamedGroupingPolicy("g", 0, "alice")用于获取策略中所有任务继承规则。
Casbin是一个强大的访问控制框架,可以为应用程序提供基于角色的访问控制(RBAC)和其他访问控制模型。NestJS是一个基于Node.js的开发框架,它使用现代的JavaScript或TypeScript语言进行开发,并且非常适合构建高度可扩展的应用程序。 在NestJS中使用Casbin,你需要安装`@casbin/node-casbin`包。然后,你需要在你的NestJS应用程序中创建一个中间件来处理请求并执行访问控制检查。以下是一个基本的示例: ```typescript import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; import { newEnforcer } from 'casbin'; @Injectable() export class CasbinMiddleware implements NestMiddleware { async use(req: Request, res: Response, next: NextFunction) { const enforcer = await newEnforcer('path/to/model.conf', 'path/to/policy.csv'); const { user } = req; const { method, originalUrl: path } = req; const allowed = await enforcer.enforce(user.role, path, method); if (!allowed) { res.status(403).json({ message: 'Forbidden' }); return; } next(); } } ``` 在上面的示例中,我们首先导入了必要的依赖项,包括`@casbin/node-casbin`和NestJS的中间件相关依赖项。然后,我们创建了一个`CasbinMiddleware`类,它实现了`NestMiddleware`接口。在`use`方法中,我们首先使用`newEnforcer`方法创建了一个新的Casbin实例,然后获取了当前请求的用户角色、请求方法和请求路径,并使用`enforce`方法执行了访问控制检查。如果检查未通过,则返回403错误。如果检查通过,则调用`next()`方法继续处理请求。 最后,我们需要将中间件添加到我们的应用程序中。你可以在`app.module.ts`文件中将中间件注册为全局中间件,也可以将其添加到特定的控制器或路由上。以下是一个示例: ```typescript import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common'; import { CasbinMiddleware } from './casbin.middleware'; import { AppController } from './app.controller'; @Module({ imports: [], controllers: [AppController], }) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer.apply(CasbinMiddleware).forRoutes('*'); } } ``` 在上面的示例中,我们将`CasbinMiddleware`添加为全局中间件,并将其应用于所有路由。你也可以使用`forRoutes`方法指定特定的路由。 这只是一个基本示例,你可以根据需要进行调整和扩展。希望这可以帮助你在NestJS中使用Casbin实现访问控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值