权限访问控制模型

在进行企业信息系统设计时,权限控制是必不可少且非常重要的一环。

目前常见的权限访问控制模型有:

DAC

DAC,即Discretionary access control,自主访问控制。

让用户自主控制权限。例如Windows的文件系统。用户自行控制哪些用户拥有哪些权限。

MAC

MAC,即 Mandatory Access Control,强制访问控制。

MAC更强调机密性,它根据权限标识进行决策。

每个对象都有一些权限标识,每个用户也有一些权限标识。用户是否对某对象有操作权限取决于双方权限标识的关系。

RBAC

RBAC,即Role-based access control,基于角色的访问控制。

RBAC是我们更会熟知也是应用最广的一种控制模型,它引入了角色的概念。

每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。如下图。

RBAC的扩展模式

  • 角色继承

  • 职责分离

    职责分离包括静态职责分离和动态职责分离。

    静态职责分离(Static Separation of Duty):用户无法同时被赋予有冲突的角色。

    动态职责分离(Dynamic Separation of Duty):用户在一次会话(Session)中不能同时激活自身所拥有的、互相有冲突的角色,只能选择其一。

ABAC

ABAC,即Attribute-based access control,基于属性的访问控制。

ABAC是一种更动态、更细粒度、更复杂的权限控制模型。

ABAC是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。

Casbin

Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。

Casbin 可以

  1. 支持自定义请求的格式,默认的请求格式为{subject, object, action}
  2. 具有访问控制模型model和策略policy两个核心概念。
  3. 支持RBAC中的多层角色继承,不止主体可以有角色,资源也可以具有角色。
  4. 支持内置的超级用户 例如:rootadministrator。超级用户可以执行任何操作而无需显式的权限声明。
  5. 支持多种内置的操作符,如 keyMatch,方便对路径式的资源进行管理,如 /foo/bar 可以映射到 /foo*

Casbin 不能

  1. 身份认证 authentication(即验证用户的用户名、密码),casbin只负责访问控制。应该有其他专门的组件负责身份认证,然后由casbin进行访问控制,二者是相互配合的关系。
  2. 管理用户列表或角色列表。 Casbin 认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是 Casbin 的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC方案中用户和角色之间的映射关系。

Python + Casbin

安装

1
$ pip install casbin

一个RBAC模型的示例:

rbac_model.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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

rbac_policy.csv

1
2
3
4
5
p, alice, data1, read
p, bob, data2, write
p, data2_admin, data2, read
p, data2_admin, data2, write
g, alice, data2, admin

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import casbin

e = casbin.Enforcer("rbac_model.conf", "rbac_policy.csv")
sub = "alice"
obj = "data1"
act = "read"

if e.enforce(sub, obj, act):
print("permit alice to read data1")
else:
print("deny the request, show an error")

roles = e.get_roles_for_user("alice")
print(roles)

输出

1
2
permit alice to read data1
['data2']

model和policy的定义详细说明在这里

Reference