一、权限系统介绍

权限系统简单定义:“who 对 what 进行 how 的操作”的表达式是否为真。
系统涉及到的概念:

  • Who:用户(user),使权限的拥有者或主体。
  • What:权限针对的对象或资源(resource)。
  • How:具体的操作权限或方法行为(operator或method)。
    引申之后,可以增加:
  • 用户组:group用户的集合,方便对一批相同的用户进行管理。
  • 角色:role权限的集合,方便对一批权限进行管理。

这里考虑用户组和角色,不考虑继承,即所有的用户组都是平级的关系,不可以继承包含,所有的角色也都是平级的关系,不可以包含和继承。
再次引申一下,资源不仅有平级的关系,还有级联的关系,拥有父级别的资源权限就有了所有子级别对应的权限了。
最后关系图如下: ua001

二、Linux权限系统介绍

以linux的文件目录的权限管理为例,linux有用户,组,权限的概念。
一个linux用户可以属于多个linux用户组;同理一个linux用户组可以有多个用户。
Linux的文件或目录有4种权限:读,写,可执行,无权限。
一个linux文件或目录只能属于一个用户和一个组。
drwxr-xr-x user_00 users 16384 Sep 23 11:14 lamp
第1位表示文件类型。d是目录文件,l是链接文件,-是普通文件,p是管道
第2-4位表示这个文件的所有者是user_00,这个用户有r读,w写,x执行的权限。
第5-7位表示这个文件的组users包含的用户,他们具有的权限是r读,x执行。
第8-10位表示既不是文件所有者user_00,也不再users这个用户组里的用户具有的权限是x执行权限。
在这里,user_00, users对应who,文件和目录对应what,,rwx对应how操作。

三、Mysql权限系统介绍

Mysql的权限涉及到user,db,host,table_priv,columns_priv,proc_priv这几张表,它是分级别的,
它的存取控制分为两个阶段, 1:服务器检查你是否有连接权限;2:你发出的每个请求都要去验证权限。
权限涉及到全局层级,数据库层级,表层级,列层级,子程序层级。
Who对应用户。
What对应db,table,view,column,process,function等。
How对应connect,select,update,insert,delete,create,drop,alter,grant,process,file,execute操作。
角色role就是一组权限的集合,通过角色,管理员可以方便的把一组权限授予某个用户。

四、通用权限系统的设计

  1. 系统注册
  2. 审批流程注册
  3. 资源、操作、审批流注册。l
  4. 权限申请,撤销,修改,删除,续期
  5. 权限审批,驳回
  6. 权限批量开通
  7. 用户组管理
  8. 角色管理
  9. 移动审批
  10. 权限校验
  11. 权限查看,权限回收
  12. 通知服务,到期提醒,审批催办
  13. 权限Api服务(申请,注册,鉴权)
  14. 操作日志

五、腾讯罗盘权限系统DB设计

1.t_priv_system 系统注册表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
create table if not exists t_priv_system(
    sys_id       bigint        primary key not null comment '主键,系统id',
    sys_name     varchar(255)  comment '系统名称',
    sys_owner    varchar(2000) comment '系统负责人,逗号分隔多人',
    sys_mark     varchar(2000) comment '系统备注,系统用途,主页url',
    vip_users    longtext      comment 'vip用户列表',
    sys_status   int           comment '系统状态',
    creator      varchar(255)  comment '创建者',
    created      datetime      comment '创建时间',
    updated      datetime      comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '系统注册表';

2.t_priv_process 权限审批流程,最多有9步审批,必须完成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
create table if not exists t_priv_process(
    proc_id         bigint          primary key comment '主键,流程id',
    sys_id          bigint          comment '流程所属系统id',
    proc_name       varchar(255)    comment '流程名称',
    creator         varchar(255)    comment '流程创建者',
    stepnum         int             comment '流程总数<10',
    stepobj1        varchar(255)    comment '步骤1审批对象',
    stepobj2        varchar(255)    comment '步骤2审批对象',
    stepobj3        varchar(255)    comment '步骤3审批对象',
    stepobj4        varchar(255)    comment '步骤4审批对象',
    stepobj5        varchar(255)    comment '步骤5审批对象',
    stepobj6        varchar(255)    comment '步骤6审批对象',
    stepobj7        varchar(255)    comment '步骤7审批对象',
    stepobj8        varchar(255)    comment '步骤8审批对象',
    stepobj9        varchar(255)    comment '步骤9审批对象',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '权限审批流程,最多有9步审批,必须完成';

3. t_priv_approvalobj 流程审批对象定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
create table if not exists t_priv_approvalobj(
    apvobj_id       bigint   primary key comment '主键,审批对象id',
    stepobj_en      varchar(255)    comment '审批步骤对象英文名,唯一索引',
    stepobj_cn      varchar(255)    comment '审批步骤对象中文名',
    is_apicall      int             comment '是否api调用',
    apiurl          varchar(255)    comment 'apiURL地址',
    apiparam        varchar(255)    comment 'api参数',
    apvobj_status   int             comment '审批对象状态',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间',
    unique key uk_obj_en(stepobj_en)
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '流程审批对象定义';

4.t_priv_resources 系统资源信息表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
create table if not exists t_priv_resources(
    prid                  bigint primary key auto_increment comment '主键,权限资源表',
    sys_id                bigint          comment '资源所属系统',
    resource_id           varchar(255)    comment '资源id',
    resource_cn           varchar(255)    comment '资源名称',
    creator               varchar(255)    comment '资源创建者',
    resource_owner        text            comment '资源负责人,分号分割',
    is_has_subresource    int             comment '是否有级联子资源权限',
    subresource_type      int             comment '子资源类型 api或本地',
    subresource_level     int             comment '字资源层数',
    subresource_apiurl    varchar(255)    comment '资源涞源 api url',
    is_canapply           int             comment '是否可以申请',
    proc_id               bigint          comment '资源申请流程id', 
    created               datetime        comment '创建时间',
    updated               datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '系统资源信息表';

5.t_priv_resource_operation 系统资源操作信息表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
create table if not exists t_priv_resource_operation(
    proid           bigint primary key comment '主键,操作id',
    sys_id          bigint          comment '系统id',
    resource_id     varchar(255)    comment '资源id',
    operate_en      varchar(255)    comment '操作英文名read,write,admin',
    operate_cn      varchar(255)    comment '操作中文名',
    creator         varchar(255)    comment '创建者',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '系统资源操作信息表';

6.t_priv_user_apply 用户权限申请表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
create table if not exists t_priv_user_apply(
    apply_id         bigint primary key comment '申请单id,主键',
    apply_user       varchar(255)   comment '权限申请人',
    apply_group_id   bigint         comment '申请组id',
    sys_id           bigint         comment '系统id',
    sys_name         text           comment '系统名称',
    permission_owner varchar(255)   comment '权限获得者',
    resource_id      text           comment '资源id 和子资源合并的',
    resource_cn      longtext       comment '资源名称 和子资源合并的',
    operate_en       varchar(255)   comment '资源操作id',
    operate_cn       varchar(255)   comment '资源操作名称',
    apply_reason     text           comment '申请原因',
    apply_daylimit   bigint         comment '申请时长',
    apply_status     int            comment '申请单状态',
    last_remind_time datetime       comment '上次催办时间',
    process_id       bigint         comment '审批流程id',
    stepnum          int            comment '审批总步数',
    currstep         int            comment '当前审批步',
    stepopers1       text           comment '步骤1所有审批人 分号分割',
    stepapprover1    varchar(255)   comment '步骤1实际审批人',
    stepresult1      int            comment '步骤1审批结果0驳回,1通过',
    stepmark1        varchar(255)   comment '步骤1审批意见',
    stepopers2       text           comment '步骤2所有审批人 分号分割',
    stepapprover2    varchar(255)   comment '步骤2实际审批人',
    stepresult2      int            comment '步骤2审批结果0驳回,1通过',
    stepmark2        varchar(255)   comment '步骤2审批意见',
    stepopers3       text           comment '步骤3所有审批人 分号分割',
    stepapprover3    varchar(255)   comment '步骤3实际审批人',
    stepresult3      int            comment '步骤3审批结果0驳回,1通过',
    stepmark3        varchar(255)   comment '步骤3审批意见',
    stepopers4       text           comment '步骤4所有审批人 分号分割',
    stepapprover4    varchar(255)   comment '步骤4实际审批人',
    stepresult4      int            comment '步骤4审批结果0驳回,1通过',
    stepmark4        varchar(255)   comment '步骤4审批意见',
    stepopers5       text           comment '步骤5所有审批人 分号分割',
    stepapprover5    varchar(255)   comment '步骤5实际审批人',
    stepresult5      int            comment '步骤5审批结果0驳回,1通过',
    stepmark5        varchar(255)   comment '步骤5审批意见',
    stepopers6       text           comment '步骤6所有审批人 分号分割',
    stepapprover6    varchar(255)   comment '步骤6实际审批人',
    stepresult6      int            comment '步骤6审批结果0驳回,1通过',
    stepmark6        varchar(255)   comment '步骤6审批意见',
    stepopers7       text           comment '步骤7所有审批人 分号分割',
    stepapprover7    varchar(255)   comment '步骤7实际审批人',
    stepresult7      int            comment '步骤7审批结果0驳回,1通过',
    stepmark7        varchar(255)   comment '步骤7审批意见',
    stepopers8       text           comment '步骤8所有审批人 分号分割',
    stepapprover8    varchar(255)   comment '步骤8实际审批人',
    stepresult8      int            comment '步骤8审批结果0驳回,1通过',
    stepmark8        varchar(255)   comment '步骤8审批意见',
    stepopers9       text           comment '步骤9所有审批人 分号分割',
    stepapprover9    varchar(255)   comment '步骤9实际审批人',
    stepresult9      int            comment '步骤9审批结果0驳回,1通过',
    stepmark9        varchar(255)   comment '步骤9审批意见',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '用户权限申请表';

7. t_priv_permission 用户,组,角色权限表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
create table if not exists t_priv_permission(
    permission_id   bigint   primary key comment '主键,权限id',
    permission_owner_type varchar(255) comment '所有者类型User,group,Role',
    permission_owner      varchar(255) comment '权限所有者',
    sys_id          bigint          comment '系统id',
    resource_id     text            comment '资源id',
    resource_cn     longtext        comment '资源名称',
    operate_en      varchar(255)    comment '操作名称',
    valid_from      bigint          comment '权限有效开始日期',
    valid_to        bigint          comment '权限有效结束日期',
    permission_status int           comment '权限状态',
    apply_id        bigint          comment '相关的申请单id',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '用户,组,角色权限表';

8. t_priv_log 操作日志表

二期工程,可以考虑扩展用户组和角色的定义及实现。

9. t_priv_group 用户组表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
create table if not exists t_priv_group(
    group_id        bigint primary key comment '组id',
    sys_id          varchar(255)    comment '关系类型,用户为主,组为主',
    group_cn        varchar(255)    comment '组名',
    creator         varchar(255)    comment '创建者',
    group_mark      text            comment '组描述信息',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '用户组表';

10. t_priv_role 角色表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
create table if not exists t_priv_role(
    role_id         bigint primary key comment '主键,角色id',
    sys_id          bigint          comment '系统id',
    role_cn         varchar(255)    comment '角色名称',
    creator         varchar(255)    comment '创建者',
    role_mark       text            comment '角色描述',
    valid_from      bigint          comment '角色有效开始日期',
    valid_to        bigint          comment '角色有效结束日期',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '角色表';

11. t_priv_ugr_relation 用户,组,角色关系表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
create table if not exists t_priv_ugr_relation(
    ugr_id          bigint          comment '主键',
    ugr_type        varchar(255)    comment '关系类型,用户为主,组为主',
    user_en         varchar(255)    comment '用户名',
    group_en        varchar(255)    comment '用户所属组名',
    role_en         varchar(255)    comment '用户所有角色名,组拥有角色名',
    creator         varchar(255)    comment '创建者',
    created         datetime        comment '创建时间',
    updated         datetime        comment '更新时间'
)
ENGINE = InnoDB
default CHARACTER SET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '用户,组,角色关系表';

六、腾讯罗盘功能模块设计

  1. 系统管理模块
    (1) 新建编辑系统
    (2) 系统查询
  2. 审批对象定义模块
    (1)新建编辑审批对象
  3. 审批流程定义模块
    (1)新建编辑审批流程
    (2)查询审批流程
    (3)查询审批流程相关的资源,申请单,权限单,权限用户
  4. 资源管理模块
    (1)新建编辑资源信息
    (2)新建编辑资源子信息
    (3)新建编辑资源操作信息
    (4)查询资源信息
    (5)查询此资源相关的申请单,权限单,用户列表,组列表,角色列表
    (6)权限用户资源操作权限清理功能
  5. 权限申请模块
    (1)用户申请资源(子资源)相关操作的权限(批量)功能
    (2)申请单状态处理
    (3)申请单查询
    (4)申请单审批进度查询
    (5)申请单催办功能(邮件,短信,微信)
    (6)批量开通权限功能
  6. 审批单管理模块
    (1)审批单查询
    (2)审批单(批量)处理
  7. 用户组管理模块
    (1)新建编辑用户组
    (2)用户组权限申请,添加,编辑
    (3)用户组成员管理
    (4)用户组角色管理
  8. 角色管理模块
    (1)角色新建
    (2)角色权限新建编辑
    (3)角色查询
    (4)角色相关用户,用户组查询
  9. 个人中心模块
    (1)资源列表
    (2)申请单列列表
    (3)所属用户组列表
    (4)所有角色列表
    (5)所有权限列表
    (6)权限续期
    (7)资源权限列表
  10. Api模块
    (1) 系统注册接口
    (2) 资源注册接口
    (3) 权限查询接口
    (4) 鉴权服务接口
    (5) 权限审批接口
  11. 移动端模块

七、腾讯罗盘权限系统用户界面设计

ua001

八、腾讯罗盘权限系统业务逻辑架构

  1. 权限申请模块
    提供一个权限后台Server, 每当有用户提交申请单,则保存之后,给后台server发送请求,后台server接受到请求后就直接返回,并开启一个任务处理此申请单的相关信息,
    主要有如下信息:
    (1)获取申请单对应的审批流程
    (2)获取每个流程步骤的审批人
    (3)更新申请单的审批人信息和审批步骤信息
    (4)通知相关人进行审批

    申请单处理主要分为两步,
    第一步就是用户提交申请单,系统会根据用户选择的目录对象情况,进行合并,生成对应的拼接好的resource_id,这个时候保存数据仅仅保存Apply_id、 Apply_user、Sys_id、Sys_name、Permission_owner、Resource_id、Resource_cn、Operate_en、 Apply_reason、Apply_daylimit、Apply_status、Updated这几个信息;同时启动后台服务,进行第二步处理。
    第二步首先获取申请单对应的系统和资源id,从而获取到对应的审批流程,然后获取审批流对应的每个步骤审批角色的实际审批人,最后更新申请单的审批信息。

    整体流程如下: ua001

  2. 权限审批模块
    这一步主要是资源的负责人对审批单进行审批操作,因为涉及到移动端审批,所以我们抽象出了审批公共操作。
    主要流程如下:
    ua001

    采用先审批先处理的模式,以先操作的为主
    ua001

  3. 权限鉴权验证模块
    用户需要传递系统id,资源id及子资源id,操作id,鉴权用户
    系统会先获取用户的角色,
    用户所属组的角色
    合并所有角色,获取角色的所有权限,
    获取用户的权限,
    获取用户所属组的权限
    合并所有的权限
    判断用户是否有对应的操作权限.

通用权限系统提供了鉴权api,供外部系统调用,判断用户是否有对相关资源操作的权限。

请求url:http://ca.oa.com/checkauth
请求参数:
{
    User_en:"",//用户名
    Obj_id:[],//资源id,存放样式如下[1001,1211,1213,54368]
    Obj_operation: "",//资源操作
    Sys_id:"" //系统id
}

整个鉴权的流程如下:

ua001

在处理鉴权参数的过程中,会把用户请求参数中的obj_id进行拼装,因为这个参数是一个数组 ,用户可以只传递一个资源id,也可以传递子资源id,例如:可以是这样[1001],也可以是这样[1001,1211],还可以是这样[1001,1211,1213],如果参数obj_id的参数有n个,那最终会形成n个条件,如对[1001,1211,1213]则会形成1001,1001|1211,1001|1211|1213,他们之间是或的关系,最后判断这些条件是否在数据库权限表t_auth_permission中是否找到对应的记录,如果可以找到,那么判断这次鉴权是成功的,否则就鉴权失败。为了加快鉴权的速度,这里还对resource_id增加了索引,同时增加了缓存处理。

整个方案的设计就可以实现,用户获得了一个父对象的权限(如手机Qzone),那么就获得了手 机Qzone级联的所有子对象的权限,实现了资源的级联管理,同时也实现了资源和操作的分离, 便于管理一个资源的不同操作权限。

  1. 罗盘权限验证介绍
    罗盘采用了cakephp框架开发,cakephp框架的执行入口是controller控制器,控制页面具体的模块。
    控制器执行过程:
    ua001

流程整理如下:

  1. Controller构造函数__construct
  2. 所有组件Components构造函数__construct
  3. 所有组件Components的initialize函数
  4. Controller的beforeFilter函数
  5. 所有组件Components的startup函数
  6. Controller的beforeRender函数
  7. Controller中View类的render函数
  8. 所有组件的shutdown函数
  9. Controller的afterFilter函数
  10. Controller页面输出

九、罗盘验证流程

  1. OaAuthComponent->startup函数
    (1) isOaDomain
    (2) checkSkipAuth($_GET[SKIP_AUTH_KEY],$_GET[‘__nocheck’])
    (3) 是否是vipController (TofService,InfoSearch)
    (4) Controller是否有skipLogin函数,有的话Controller->skipLogin
    (5) 敏感权限检查会话获取用户名
    (6) tof获取员工信息
    (7) controller->isAuthorized() 函数调用

  2. ReportsController中 isAuthorized 时候要checkProductAuth
    ReportsController中isAuthorized 验证流程
    (1) checkSkipAuth
    (2) 管理员跳过权限验证
    (3) 报表开发负责人和产品负责人验证
    (4) 报表白名单访问验证
    (5) 报表合作者访问验证
    (6) 报表所属产品的负责人验证
    (7) checkProductAuth($productId); //用户的产品权限验证

  3. AppController中 getUserDepProdInfo时候要checkProductAuth

  4. WxController中getUserDepProdInfo时候要checkProductAuth

  5. CustomReportController中 config时候要checkProductAuth

十、腾讯罗盘权限系统接口Api设计

  1. 系统注册api
  2. 资源查询api
  3. 用户角色查询api
  4. 角色权限查询api
  5. 用户组查询api
  6. 组角色查询api
  7. 组权限查询api
  8. 用户权限查询api
  9. 鉴权api
  10. 操作查询api

十一、权限系统容灾设计

权限系统是一个开放的通用的部门级别的系统,可以为各种系统提供权限管理功能。 层级定义.