MIS系统中的权限设计
2015-09-03 11:58
369 查看
MIS系统中的权限设计
MIS系统中的权限设计版本记录
引言
数据库设计
功能权限
模块表设计
权限表设计
菜单表设计
角色模块权限表
方法权限表
资源权限和组织可见性
组织可见性
用户和组织关系
私有资源可见性
共享资源的可见性控制
角色和属性可见性
平台设计方式
组织和角色可见性
版本记录
文档版本 | 更新时间 | 内容 |
---|---|---|
1.0.1 | 2015-9-13 | 增加共享资源可见性控制内容 |
1.0 | 2015-9-3 | 初始版本 |
引言
在MIS系统中,很常见的一个问题就是权限的设计。而权限的设计在终端的表现上又区分为对资源的权限,对菜单可见性的控制,对功能使用的限制等。有些系统中会对按钮,对菜单,对功能,对资源都分别进行设置。这样不仅实际上使用不方便,而且对于后台设计而言也是不容易的。因此,今天来从另一种思路来进行一个权限系统的设计。在权限系统的设计中,权限设计分为两大块,一块是功能权限,一块是资源权限。
- 功能权限:
功能权限指的是针对某一个功能,某个用户是否可以使用。在界面上的表示形式则为该菜单用户是否可见(比如左侧的导航菜单,比如工具栏的一些添加,删除等功能按钮),以及在非法调用该功能API时是否会被拦截。
- 资源权限:
资源权限指的是对于某一个资源(文档,项目表之类的东西),某个用户是否可以访问,是否可见,是否可以操作等。
本文的权限设计就从这两个点出发,进行设计。
整个权限系统的实现,是一个从数据库设计到代码设计相互配合的过程。当然,代码上的设计相对简单,数据库的设计则是其中的重点,数据库的设计决定了代码将要如何配合来实现整体的权限思想。
数据库设计
功能权限
在设计功能权限之前,首先需要明确的一点就是对于每一个功能(也就是程序里的对应方法),都有一个权限对应,而用户使用该功能的时候就需要验证该功能是否在用户的权限列表中。为此我们使用一种ACL的验证方式。ACL验证模式
将一个二进制的数字表示为一个功能的权限。比如读取用户的功能的权限是0x00000001,请注意,这个权限数字是针对具体模块有效的。然后A用户自身的权限集合是0x01010101011。那么验证A是否可以读取用户,可以使用功能的权限数字与用户的权限集合进行“与“运算。如果运算后的结果与功能的权限数字相等,则意味着具备该权限。此种方法具备速度快而且同时验证多个权限组合(验证权限组合的方法先将权限组合进行”并“运算,然后再与用户的权限列表进行”与“运算)。
基于ACL的验证方式,可以使我们快速的完成对一个功能进行权限验证。而这个验证的核心思想就是为一个用户分配每一个功能模块的权限,而每一个具体的功能必然都隶属于某一个模块,并且要求具体的权限。将这个功能要求的模块权限与用户持有的权限集合进行比对即可知道用户是否有权使用该功能。下面进入到具体的数据库设计。
模块表设计
模块表用来存储系统中不同的模块,用于对功能进行大粒度的区分id | 模块名称 |
---|---|
1 | 用户管理 |
2 | 角色管理 |
权限表设计
权限表用来存储具体每一个模块下面都有什么样的权限,以及每一个权限自身对应的权限数字id | 模块 | 功能名称 | 权限 |
---|---|---|---|
1 | 1 | 搜索用户 | 0x00000001 |
2 | 1 | 增加用户 | 0x00000010 |
3 | 1 | 删除用户 | 0x00000100 |
4 | 1 | 更新用户 | 0x00001000 |
5 | 2 | 搜索角色 | 0x00000001 |
6 | 2 | 增加角色 | 0x00000010 |
7 | 2 | 删除角色 | 0x00000100 |
例子:
如果一个用户拥有”用户管理”模块的搜索用户和增加用户的权限,则该用户该模块持有的权限为0x00000011.也就是两个功能的权限的并运算结果。
菜单表设计
在权限管理中,一个很重要的终端效果就是对于没有特定权限的用户,菜单是隐藏的。一般而言,菜单包含左侧的导航菜单,中央显示区域的工具栏菜单。对于这种需求,就需要有一个菜单表进行能够显示的拦截。Id | 菜单名称 | 父菜单id | 对应模块 | 所需权限 | 菜单位置 | 菜单顺序 |
---|---|---|---|---|---|---|
1 | 用户管理 | 0 | 1 | 0x00000001 | 左侧菜单 | 0 |
2 | 增加 | 1 | 1 | 0x00000010 | 工具栏菜单 | 1 |
3 | 删除 | 1 | 1 | 0x00000100 | 工具栏菜单 | 2 |
4 | 编辑 | 1 | 1 | 0x00001000 | 工具栏菜单 | 3 |
5 | 查看详细信息 | 1 | 1 | 0x00010000 | 工具栏 | 4 |
6 | 角色管理 | 0 | 2 | 0x00000001 | 左侧菜单 | 1 |
7 | 增加 | 6 | 2 | 0x00000010 | 工具栏 | 2 |
8 | 删除 | 6 | 2 | 0x00000100 | 工具栏 | 3 |
比如需要展开左侧的导航菜单树时,只需要查询出所有的左侧菜单,并且按照权限(也就是并运算后等于菜单权限自身的),将不可见的删除结合父菜单id就组合成了菜单树。
如果一个菜单不需要权限就能显示,那么只要将该菜单的权限数字定为0即可
在上表中可以看到,工具栏菜单的父菜单都是左侧菜单。这里的父菜单作用不是用来生成菜单树。一般,左侧导航菜单点击后,都会有一个中央区域用来显示具体的资讯内容。而在该页面,工具栏要显示什么菜单,就由这个导航菜单下的子菜单,也就是工具栏菜单来决定。
例子:
比如用户对于用户管理的权限是0x00000011,则用户点击用户管理后,在该页面只能看到增加一个按钮
角色模块权限表
在ACL的设计方式中,用户的权限粒度只设计到模块这一层,但这其实已经足够使用。用户对每一个功能的权限判断,实际上就是该功能所需要的模块权限,和用户持有的模块权限的对比判断。而每一个角色所拥有的权限则是通过角色模块权限表来确定的,也就是需要确定对于每一个模块,角色拥有什么样的权限。
这里权限设计采用一个取巧的方式,以KV方式存储。权限中使用字符串来表示。每个模块用
,区隔,每个内容中key是模块id,value是角色对该模块权限。kv以
:区隔
Id | 角色id | 权限 |
---|---|---|
1 | 1 | 1 |
那么如何为每一个角色进行权限信息的生成呢。可以在编辑角色的时候,使用一个树状菜单来表示所有可以编辑的权限。然后通过菜单传递权限表中的项的id过去即可。
这里需要特别注意并且在任何方面都需要遵守的是一个授权原则,如下。
角色是由具备创建角色权限的用户创建的。那么该角色的角色权限不能超过创建者本身的权限。
方法权限表
在权限系统中,每一个方法都有一个权限对应(无权限要求的方法,其权限数字为0)。这个权限信息可以以注解的方式写在源代码上,也可以记录在数据库中,因为一般方法的所需权限信息是不会更改的,所以注解方式写在代码里通过aop进行读取和判断是一种比较可行的方式。而如果要设计在数据库里,一般表结构如下id | 方法名 | 模块id | 权限数字 |
---|---|---|---|
1 | UserAction.get | 1 | 0x00000010 |
2 | UserAction.delete | 1 | 0x00000100 |
资源权限和组织可见性
在一些系统中存在资源权限的概念。比如A公司的老总可以查看该公司下的所有资料,而A公司下的B部门的部门经理只能查看B部门下的资料,而B部门下的C项目项目经理只能查看该项目的资料。还比如其他部门只能查看本部门的人事信息,而人事部门可以查看全公司的人事信息等等。在这些系统中均存在对资源可见性控制的要求。而资源权限就是为了处理资源可见性的问题。组织可见性
一般认为,子组织的资源对父组织是可见的。而不同的平行组织之间的信息是无法直接共享查看的。由此可见组织关系是很重要的。首先设计组织关系表。Id | 组织名称 | 父组织id |
---|---|---|
1 | 公司 | 0 |
2 | 开发部 | 1 |
3 | 设计部 | 1 |
4 | 人事部 | 1 |
Id | 组织id | 可见组织id |
---|---|---|
1 | 4 | 1,2,3 |
用户和组织关系
用户是在组织之中,用户一个时刻只能属于一个组织(有时候一个用户拥有多个组织的身份信息,一般是登陆的时候指定)。组织不存储用户信息,用户和组织是多对一关系。私有资源可见性
资源的权限其实就是资源可见性的表述。针对文档,通讯录,信息等,将其抽象认为是一种资源。那么这种资源应该存在对某一个组织的从属信息。因为某一个资源是属于某一个组织的。这里的资源表通过资源类型进行划分,但是在实际的设计中为了方便查询,可以将资源表设计很多份。不同类型的资源都各自设计一张表。Id | 资源名称 | 父资源id | 所属组织id | 资源类型 |
---|---|---|---|---|
1 | Demo开发项目 | 0 | 1 | 项目 |
2 | 开发文档1 | 1 | 1 | 文档 |
3 | 开发文档2 | 1 | 1 | 文档 |
4 | 视觉设计项目 | 0 | 1 | 项目 |
5 | 设计文稿1 | 4 | 1 | 文档 |
6 | 设计文稿2 | 4 | 1 | 文档 |
当用户需要查询的时候,只可以查询自身组织,或者子组织,或者可见性组织下的资源。这样就做到了对资源可见性的控制。
共享资源的可见性控制
有些时候,希望一些资源是有限共享的,比如一些资料是某一个部门以及其所有的子部门都可见,或者有些新闻希望是公司可见。这种资源和私有的资源不同,私有资源只允许自身或者上级查看。而共享资源往往是事先指定的观看范围的人员可以观看。这种需求需要设计一张共享资源表。Id | 资源名称 | 父资源id | 所属组织id | 资源类型 | 可见组织id |
---|---|---|---|---|---|
1 | 开发文档1 | 1 | 1 | 文档 | 0 |
2 | 开发文档1 | 1 | 1 | 文档 | 1 |
3 | 设计文稿1 | 4 | 1 | 文档 | 0 |
4 | 设计文稿1 | 4 | 1 | 文档 | 1 |
在实际的操作中,每次都进行组织可见性选择是比较繁琐的事情,可以创建一些群组,群组中都是事先包含好的组织id,将可见性由具体的组织替换成对应的群组可以在操作上提升便捷性,但是后台的处理流程是相同的。
角色和属性可见性
在一些系统设计中,存在着对不同的用户对同一份资源的不同字段可见性的控制要求。比如在CRM系统中,有一些用户在查看用户信息时,是无法查看用户的联系方式等要求。在这种情况下,就需要建立一个角色和字段可见表。id | 角色id | 属性名称 | 属性模块 |
---|---|---|---|
1 | 1 | name | user |
2 | 1 | age | user |
平台设计方式
组织和角色可见性
在一般的系统中,角色和组织是没有关系的,整个大系统使用一套角色体系。在选择角色时,所有的角色都是可见的。但是也存在一种需要,每一个组织需要创建自己的角色。平行组织创建的角色互不可见。那么这个时候就需要一个组织和角色的对应表。并且最初的用户和最大的超管是系统中固有存在的。而具备创建角色权限的用户所创建的角色的权限不会超过该用户本身。此时角色也可以认为是资源,同样遵循子组织的角色父组织可见,平行关系组织之间角色不可见。角色组织表设计如下
id | 角色id | 组织id |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
参考电商平台。电商平台自身也有很多角色进行不同的操作。而在电商平台入驻的这些商家也会有自身的创建角色的需求,并且商家自身也会有需要分配角色和用户的需求。在这种时候,将电商平台的组织和商家的组织放在同一张表中作为上下级组织关系也是可以的。但是放在不同的表中显然是会更加合理一些。
在这样的情况下,可以设计两张组织表,两张角色表。分别对应平台的组织,入驻平台的机构。平台中的超管角色可以新建入驻机构的信息,并且新建一个入驻机构的超管。换言之,有平台超管和机构超管两类。后者的权限只能到达机构级别,这个可以在建立机构超管时由程序限定。
这样在程序设计上就有两套管理系统,平台管理和机构管理。不同的登录界面查询不同的组织和角色表。
以平台为例,平台管理员新建机构时可以先新建机构组织本身,然后创建机构超管,将机构超管的组织设置为该机构。即可。
相关文章推荐
- gcc/g++动态链接库和静态库的链接顺序
- 在Win10 Mobile越狱解锁部署的基础 公布替换字体教程
- CentOS安装JAVA
- 海量数据问题
- IE10-浏览器实现placeholder效果
- 百钱百鸡
- 将同一用户的某一字段的所有内容拼接在一起
- 【HDU1083】【最大二分匹配】
- SEO生命周期,别做死了都不知道!
- 设计模式之依赖倒置原则
- Win10 Mobile越狱解锁部署:一款替换字体的应用程序出现
- 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路
- Bash 里的转义序列
- 设计模式之:适配器模式
- 公有ip地址 和内网ip地址
- 将相机/相册的图片保存到本地沙盒
- C# Excel 为图表添加趋势线、误差线
- 【android】 如何把gif图片下载到本地
- Regionals 2014 >> Latin America
- JS-案例-节点交换