常见权限模型与Casbin Golang实现ACL、RBAC、ABAC

1,869 阅读4分钟

前言

在应用开发中,为了保证资源的安全,经常设计一个资源授权系统来实现资源授权和权限。在动手开发前,我们需要了解常见有五种权限模型: ACL(权限控制列表)、RBAC(基于角色的访问控制)、ABAC(基于属性的访问控制)、DAC(自主访问控制)和MAC(强制访问控制)。其次,为了避免重复造轮子,我们需要了解一些优秀的开源库,如 Casbin 是一个功能强大且高效的开源访问控制库,支持各种访问控制模型以全面执行授权,支持访问控制模型,

本文主要介绍常见五种权限模型以及如何使用Casbin Golang来实现ACL、RBAC和ABAC。

常见的权限模型

  1. ACL(Access Control List 访问控制列表) ACL 是最基本和最简单的权限模型之一。它使用一个访问控制列表,列出了每个资源和允许访问该资源的用户或用户组。每个资源都有一个相关联的访问控制列表,控制了对该资源的访问权限。
  2. RBAC(Role-Based Access Control 基于角色的访问控制) RBAC 允许基于职位进行访问。RBAC 在很大程度上消除了提供对象访问权限时的自由裁量权。例如,人力资源专家不应该拥有创建网络帐户的权限;这应该是为网络管理员保留的角色。
  3. ABAC(Attribute-Based Access Control 基于属性的访问控制) 一种访问控制范例,通过使用评估属性(用户属性、资源属性和环境条件)的策略将访问权限授予用户
  4. MAC(Mandatory Access Control 强制访问控制) 在 MAC 中,用户没有太多自由来确定谁有权访问其文件。例如,用户的安全许可和数据的分类(机密、秘密或绝密)被用作安全标签来定义信任级别。
  5. DAC(Discretionary Access Control 自主访问控制) 在 DAC 中,数据所有者决定谁可以访问特定资源。例如,系统管理员可以基于某些权限创建要访问的文件的层次结构。

更多可以参考 访问控制模型

Casbin实现

Casbin 使用配置文件来定义访问控制模型。分别是:model.conf和policy.csv 。其中

  1. model.conf存储访问模型
  2. policy.csv存储具体的用户权限配置

Casbin的使用非常简单。我们只需要创建一个主要结构:enforcer。当构造这个结构时,model.conf和policy.csv就会被加载。

ACL

接着,我们以使用Casbin库实现ACL权限模型。

创建model.conf

#请求定义
[request_definition]
r = sub, obj, act

#策略定义
[policy_definition]
p = sub, obj, act

#策略效果
[policy_effect]
e = some(where (p.eft == allow))

# 匹配器定义
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

创建policy.csv

p, alice, data1, read
p, bob, data2, read

运行一个简单的ACL例子 example.go:用户(user)对数据(data)的读写(read)操作

package main

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

func main() {
	e, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
	if err != nil {
		panic(err)
	}
	sub := "alice" // 想要访问资源的用户。
	obj := "data1" // 将被访问的资源。
	act := "read"  // 用户对资源执行的操作。

	allowed, err := e.Enforce(sub, obj, act)
	if err != nil {
		panic(err)
	}
	if allowed {
		fmt.Println("Access granted")
	} else {
		fmt.Println("Access denied")
	}
}

运行输出

Access granted

RBAC

实现 RBAC 权限模型和ACL相似,多了角色定义, 其一,在模型配置定义角色、用户和权限,其二,在策略文件中指定用户-角色和角色-权限的关联。

model.conf

[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.csv

p, alice, data1, read
p, bob, data2, read

#关联
g,alice,data2_admin  

测试一下,同样运行example.go

运行输出

```js
Access granted

ABAC

实现 ABAC 权限模型,其一,在模型配置中定义资源、用户属性和环境属性,其二,在策略文件中指定策略规则。 model.conf

[request_definition]
r = sub, obj, act, resource

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

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

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

policy.csv

p, alice, data1, read, attribute1:value1
p, bob, data2, read, attribute1:value2

我们将上例example.go修改为ABAC的测试

package main

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

func main() {
	enforcer, err := casbin.NewEnforcer("./model.conf", "./policy.csv")
	if err != nil {
		panic(err)
	}

	// 检查访问权限,包括属性
	allowed, err := enforcer.Enforce("alice", "data1", "read", "attribute1:value1")
	if err != nil {
		fmt.Println("Failed to enforce policy:", err)
		return
	}

	if allowed {
		fmt.Println("value1 Access granted")
	} else {
		fmt.Println("value1 Access denied")
	}

	// 检查访问权限,包括属性
	allowed, err = enforcer.Enforce("alice", "data1", "read", "attribute1:value2")
	if err != nil {
		fmt.Println("Failed to enforce policy:", err)
		return
	}

	if allowed {
		fmt.Println("value2 Access granted")
	} else {
		fmt.Println("value2 Access denied")
	}
}


运行输出

value1 Access granted
value2 Access denied

总结

ACL权限模型较简单,不够灵活,功能单薄。RABC是比较常见,比如PostgreSQL作为其主要权限模型。ABAC提供了更动态的访问控制形式,基于属性的访问控制,比如阿里云的RAM都是ABAC 类型的权限访问服务。随着应用规模的增长,角色数量越来越多,选择适合的权限模型尤为重要。 Casbin可以简单的支持各种访问控制模型,还提供多种的adapter(file、sql、orm等类型) 实现,支持较多语言比如扩展到Go、Java、Node.js、Javascript(React)、Python、PHP、.NET、Delphi、Rust等,是个值得学习的统一访问控制框架。

参考