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
- Host: GitHub
- URL: https://github.com/guotie/acl
- Owner: guotie
- Created: 2017-03-30T10:32:25.000Z (about 9 years ago)
- Default Branch: master
- Last Pushed: 2017-04-01T00:51:34.000Z (about 9 years ago)
- Last Synced: 2024-10-18T09:30:57.121Z (over 1 year ago)
- Topics: acl, authorization, go, permission, rbac
- Language: Go
- Size: 35.2 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
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 保存;