An open API service indexing awesome lists of open source software.

https://github.com/guotie/acl

acl based permission
https://github.com/guotie/acl

acl authorization go permission rbac

Last synced: 10 months ago
JSON representation

acl based permission

Awesome Lists containing this project

README

          

# ACL access control list

参考借鉴 shiro和spring security的权限管理, 100% 测试覆盖

# 名词概念

## ACL
访问控制列表。

## Rule
权限判断辅助规则, 目前需要硬编码。

在有些时候,ACL判断规则会比较繁琐,例如:

在分级权限管理中,假如分为四级:总部级,省级,市级,县级。
省级管理人员可以管理下面所有市级、县级的营业厅,市级管理人员可以管理所有的本市的营业厅和下面县的营业厅,A市共有100家营业厅。

如果按照ACL的规则,则需要给省级管理人员配置所有营业厅的管理权限,就是需要N条记录。而且,每增加、删除营业厅,都需要重新修改权限
的ACL规则。

按照rule的配置规则,则仅仅需要编写一个函数,判断省级的管理人员是否有该营业厅的权限即可。

当然,rule函数规则和业务关联紧密,需要在代码中写死,灵活性欠缺。

## Principal

一个接口,特指Account或者Role

# 用法说明

## 权限主体 Account

你需要自己定义Account Model,并为Account实现 Principal 接口的两个方法:

```
type AclObject interface {
GetSid() string // 通常是 uuid
GetTyp() string // object类型, user, role, post, etc...
}

type Principal interface {
AclObject
}

```

Account 的 GetSid方法返回Account的Sid,通常为UUID
Account 的 GetTyp方法返回 _*acl.AccountTyp*_, 为"AccountTyp"

## 权限标的

Account 要操作的权限标的必须实现 AclObject 接口.

权限标的 GetTyp 方法返回权限标的 类型。

## 角色Role

角色最重要的两个接口:

1. 创建角色
```
func (mgr *AclManager) CreateRole(name, sid, depart, corp, city, province string, level int) (*Role, error) {
```
- name: 角色名称
- sid: 角色全局id, 通常为空, 由uuid自动生成
- depart: 角色所在部门
- corp: 角色所在公司
- city: 角色所在城市
- province: 角色所在省份
- level: 角色级别

2. 将Account加入到角色中:
```
func (mgr *AclManager) AddUserRoleRelation(uid, rid string) error
```
- uid: Account的uuid
- rid: role的uuid

## Permission

Permission 比较简单, 核心是一个类型为uint32, 名为Mask的字段。 通过 请求的操作权限 与 AclEntry 中的权限做 & 操作, 来决定是否具备操作权限

Mask每一位代表一种权限,目前已定义的权限如下:
```
PermissionRead = 1 << permIndexRead // 读权限
PermissionWrite = 1 << permIndexWrite // 写权限
PermissionCreate = 1 << permIndexCreate // 创建权限
PermissionDelete = 1 << permIndexDelete // 删除权限
PermissionManage = 1 << permIndexManage // 管理权限
```

## 权限访问控制列表 AclEntry

通过AclEntry来控制一个账号或一个角色是否对权限标的有特定的权限

创建ACL entry:
```
func (mgr *AclManager) CreateACE(whoSid, whoTyp, whatSid, whatTyp string, mask uint32, order int,
grant, auditSuccess, auditFailure bool) (*AclEntry, error)
```

- whoSid: 权限主体sid
- whoTyp: 权限主体类型, 通常为AccountTyp或RoleTyp
- whatSid: 权限标的sid
- whatTyp: 权限标的类型
- mask: 权限
- order: 创建的Acl在Acl list的顺序, 判断权限时, AclEntry安装order从小到大逐条判定
- grant: 授权或拒绝
- auditSuccess: 当授权时, 是否审计
- auditFailure: 当拒绝时, 是否审计

## AclManager
```
func CreateAclManager(db *gorm.DB, pool *redis.Pool) *AclManager
```
CreateAclManager 用来创建 AclManager 对象

在上面的工作都准备好以后,就可以通过IsGrant接口来查询权限:
```
func (mgr *AclManager) IsGrant(who AclObject, what AclObject, perm Permission) bool {
```
- who: 权限主体, 可以是Account,也可以是Role
- what: 权限标的
- perm: 请求的权限
- 返回: true: 授权 false:拒绝

# 权限判断流程

权限判断通过这个接口来查询:

```
func (mgr *AclManager) IsGrant(who AclObject, what AclObject, perm Permission) bool
```

流程:

0. 首先,根据who查找who的principls, 即who本身和who所属的roles;

1. 对于who所属的每个principal:

a. 查找who关联的rules, 轮询每条rule, 该rule 是否能够判定权限, 如果该rule判定出权限(Grant或Reject), 返回权限; 否则, 返回0;

b. 查找who关联所有 acl, 轮询每条acl, 该acl 是否能够判定权限, 如果能判定出权限(Grant或Reject), 返回权限; 否则, 返回0;

2. 如果以上步骤未判定出权限, 返回拒绝(Reject)

## 缓存

查询权限时,优先从缓存中查找。

缓存使用redis保存,主要有以下2种:

1. user对应的角色列表, 使用 redis set 保存;
2. principal 对应的 acl 列表, 使用 redis hashmap 保存;