来源:https://blog.csdn.net/u010004317/article/details/53996757
导言
最近花了一段时间在做权限开发者一块,从设计到编码,我都全程参与了,对权限开发也有了一个本质上的了解,权限管理作为一个系统最基本也是最重要的功能之一,在一个系统中是非常重要的,今天我就侃大山,聊聊我这个系统的权限开发的一些东西,与大家交流交流。
1、系统的原有权限管理模式
之前这个系统的权限管理是通过配置文件来处理的,大概流程是这样的,把用户分成多个用户组,然后每个用户组对应着多个用户的id,每次访问页面的时候,都会读取这个配置文件的信息,判断登录用户的id属于哪个用户组,然后在页面判断这个用户组是否有访问这个链接的权限。配置文件的格式是这样的: {"adm" : [1,2,34], "dev" : [5,6,1]}
这样会带来什么问题呢?有以下几个:
- 权限管理混乱,一个用户id可能会在多个权限组中
- 每次更新配置文件,都要重新上线,麻烦
- 没有图形化界面,配置权限困难
- 页面有太多的if判断语句,造成代码可读性差
2、新的权限管理开发
这里要强调一遍,这个系统数没有用外面流行的框架的,都是jsp加上之前封装的框架来使用的,所以你们可以发现我这个权限开发是没有用到以前用框架开发权限要用到的过滤器,监听器之类的,或者你可能会说,没有用框架也可以用过滤器和监听器啊,因为这是Servlet的东西。在这里我要解释一下,现在市面上的权限管理我个人觉得大致可以分为两种:
-
用户进入系统的时候不判断权限,把系统中的所有功能入口都开发给用户,每次用户点击相应的功能入口时,通过链接和用户判断该用户是否有使用该功能的权限,有权限则进入,没有权限则跳转到没权限的提示页面,这种功能一般都是使用过滤器来完成的
-
在用户进入系统的时候就判断用户的权限,根据用户的权限开发相应的功能入口,不同权限的用户看到的页面是不一样的。相比第一种来说,这种的好处是可以屏蔽掉用户没有权限访问的功能入口,用户只能看到自己权限所拥有的功能入口,而根本不知道该系统还有什么功能,更有利于保密。但是,如果只是在用户进入系统的时候就判断权限,以后不再判断,那么就会出现第一种情况中不会出现的问题,那就是 权限试探 ,我可以通过模拟地址栏的形式,不断地改变参数(有些提交方式不得不是get提交,所以地址栏难免会带有参数)来达到破坏权限的目的,代码写得不严谨,这个问题就会发生在你的系统上,比较好的做法就是,在每一次访问页面的时候,都重新再判断一次权限。所以本来就不需要使用过滤器的地方又得再使用上了。
然并卵,因为系统的特殊性,该系统的权限开发都不会用到过滤器和监听器,所有的权限判断都写在了一个公用页面上,然后再在每个页面上include进去,也达到了类似于过滤器的效果,然而,我是不赞成这样的写法的,框架、过滤器能存在,自然有他们的道理,我之前也做过用框架的权限开发,觉得那样更方便,当然,这是题外话了。
(1) 数据库设计
话说刚开始在设计数据库的时候还是碰到不少壁的,因为头脑中还是留存着系统原有权限管理的余威,在最初设计的时候还受到它的一点影响,后来,干脆就不参考以前的权限管理模式了,做出自己的一套出来 。
用户表(acctUser)
字段 | 类型 | 描述 |
---|---|---|
id | int(11) | 用户唯一标识,主键 |
acct | varchar(20) | 账号 |
name | varchar(20) | 姓名 |
createTime | int(11) | 用户的创建时间,时间戳 |
lastLoginTime | int(11) | 用户的最后登录时间,时间戳 |
del | int(1) | 是否删除,逻辑删除,1为删除,0为非删除 |
mobile | varchar(20) | 用户手机 |
enail | varchar(50) | 用户邮箱 |
remark | varchar(200) | 用户备注 |
角色表(acctRole)
字段 | 类型 | 描述 |
---|---|---|
roelId | int(11) | 角色唯一标识,主键 |
roleName | varchar(30) | 角色名 |
roleDescribe | varchar(30) | 角色描述 |
权限表
在该系统中,权限会被精细化三种权限,第一种是导航栏的权限,第二种是侧边栏权限,最后一种是页面的按钮和业务权限,如下图所示
导航栏权限表(acctHeaderMenuPermission)
字段 | 类型 | 描述 |
---|---|---|
headerMenuId | int(11) | 导航栏权限唯一标识,主键 |
headerMenuName | varchar(30) | 导航栏权限菜单名 |
headerMenuUrl | varchar(255) | 导航栏权限菜单URL |
menuOrder | tinyint(3) | 导航栏权限菜单的顺序,展示的时候根据这个字段来排序 |
侧边栏权限表(acctSideMenuPermission)
字段 | 类型 | 描述 |
---|---|---|
sideMenuId | int(11) | 侧边栏权限唯一标识,主键 |
sideMenuName | varchar(30) | 侧边栏权限菜单名 |
sideMenuUrl | varchar(255) | 侧边栏权限菜单URL |
headerMenuId | int(11) | 侧边栏权限菜单所对应的导航栏权限菜单Id,外键 |
menuOrder | tinyint(3) | 侧边权限菜单的顺序,展示的时候根据这个字段来排序 |
业务或者操作权限表(acctDetailMenuPermission)
字段 | 类型 | 描述 |
---|---|---|
menuId | int(11) | 权限唯一标识,主键 |
menuName | varchar(30) | 权限菜单名 |
sideMenuId | int(11) | 页面业务或操作权限对应的侧边栏权限菜单Id,外键 |
bizOrOperate | tinyint(3) | 该权限所对应的业务或操作 |
用户角色表(acctUserRole)
字段 | 类型 | 描述 |
---|---|---|
acctId | int(11) | 用户Id,外键,主键 |
roleId | int(11) | 角色Id,外键,主键 |
角色-导航栏权限表(headerMenuRole)
字段 | 类型 | 描述 |
---|---|---|
menuId | int(11) | 权限Id,主键,外键 |
roleId | int(11) | 角色Id,主键,外键 |
角色-侧边栏权限表(sideMenuRole)
字段 | 类型 | 描述 |
---|---|---|
menuId | int(11) | 权限Id,主键,外键 |
roleId | int(11) | 角色Id,主键,外键 |
角色-业务或操作权限表(detailMenuRole)
字段 | 类型 | 描述 |
---|---|---|
menuId | int(11) | 权限Id,主键,外键 |
roleId | int(11) | 角色Id,主键,外键 |
数据库模型图
(2) 页面设计
页面设计也是个很难堪的东西,在网上找了好多权限分配的图片,发现很多都不符合我现有系统的情况,后来纠结了一下,还是决定采用树形结构和弹窗相结合的方式来实现权限和角色的分配
权限管理初始化页面
该系统有三级权限,分别为导航栏权限、侧边栏权限和业务/操作权限,互成父子关系,刚好对应树的父子节点,在每个节点后面都有添加、编辑和删除按钮
增加权限
点击“添加权限”的按钮,就会有弹窗让用户添加相应的权限,每次添加权限都要选择该权限所对应的父节点,权限名,权限URL和权限展示顺序。可能有读者对于权限URL不是很了解,我在这里解释一下,因为系统本身的原因,每个权限其实就是对应着页面的每个菜单,每个菜单肯定都有自己的URL,如果某个用户有这个菜单的权限,自然就有了访问这个URL的资格
编辑权限
编辑权限和添加权限是差不多的,这里就不再赘述
删除权限
删除权限,因为权限之间是有父子关系的,在数据库中表现为主外键关系,数据库的外键关系为级联,也就是说如果父权限被删除了,与它对应的所有子权限也将被删除。其实这个外键对应关系我刚开始是限制在有子权限的情况下不能删除父权限的,后来经过考虑,综合了自己和系统本身的很多因素,还是把外键关系设置为级联的了。但是级联删除有个坏处,如果在删除子节点成功后,删除父节点失败了,那么就会出现删除不完全的情况,可能会出现不可预知的错误,因此,在做删除操作的时候,我都会开启一个事务,如果删除失败我就回滚,删除成功才提交事务,遵循数据库的ACID
角色管理初始化页面
角色管理和用户管理其实大同小异,所以就只讲角色管理这一模块,不讲用户管理了,角色管理这一块,是采用表格的形式来展示的,每次修改、添加用户却使用弹窗来实现的,发现弹窗真的是个好东西,又不占篇幅,又能阻塞代码
添加角色
角色添加会把当前所有的权限用属性的结果列出来,让用户可以一目了然地看到当前的所有权限以及权限的对应关系
总结
代码部分由于涉及到隐秘,我就不贴出来了,其实都是大同小异。角色-权限,每个人都可以有自己的实现方式,当然很多方式都可以实现,你也可以用配置文件,也可以用现成的权限框架,当然也可以像我一样自己写一个,只要自己喜欢和业务需要。今天写这篇博客,主要是因为之前做这个权限开发的时候,花了好多时间在角色-权限的设计上,真正开发花的时间却不多,所以我这篇博客大部分讲的是权限和角色分配上的设计和规划,主要是想起到抛砖引玉的作用,希望针对我这系统的权限开发有更好的解决方案,同时也希望这篇博客可以给那些有同样需求的人一些启发。
问:请问子权限和父权限的关系是什么啊,是子权限有父权限所有的权限再加上自己额外的权限,还是自己继承父权限中的其中一部分啊。
答:权限一般没有继承关系的,父权限控制用户进入首页看到的内容,子权限控制对某个菜单的具体操作