简述:
权限是什么?针对我们后台系统简单说,就是不同用户登录后,看到的模块-菜单-功能按钮的维度不同。本次主要讲权限模块表设计、表关联关系、如何做到权限控制、以及登录过程后台都发生了什么。我们的后台涉及到两个权限角色,一个是针对平台管理员、供应商管理员的大权限角色 sys_role;一个是针对平台、供应商普通员工的小权限角色 company_role。管理员涉及到:role.xml功能菜单树、sys_role,sys_admin,customer_info三张表和sysAdiminLogin视图;普通员工涉及到:role.xml功能菜单树、company_role公司角色表,company_dept公司部门表,company_user公司员工三张表和adminLogin视图。这里只讲大权限表关系,小权限表关系类似。角色表sys_role和功能菜单是多对多的关系,一个角色可以有多功能菜单,一个功能菜单也可以对应多个角色;管理员表sys_admin和角色表sys_role是多对一的关系,及一个管理员只能有一个角色,但一个角色可对应多个管理员(其它平台一般设计成多对多的关系,他们的角色表是针对于模块。如商品角色、订单角色等),本质上是一样的,我们角色可对应多个模块的功能菜单。我们菜单功能数据使用xml文件管理的,好处的可以降低数据库呀压力;不太方便的是每增加菜单或功能都要重新部署平台模块。登录发生了什么:根据账号和密码查询数据库,若验证通过拿到登录者信息(含拥有的功能权限ID逗号拼接),将该信息放到缓存中并返回token给前端。前端拿着token、sign数据请求用户菜单信息接口,根据返回数据展示对应模块菜单信息。所登录的用户共4种,1-平台管理员,2-平台员工,3-供应商管理员,4-供应商员工。(其中供应商登录者最多只能看到平台为该供应商管理员指定的角色权限功能)。
一:表设计
sys_role:平台角色权限表,用于管理员(平台-供应商)
CREATE TABLE `sys_role` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '权限值ID:自增', `role_name` varchar(30) NOT NULL COMMENT '角色名称', `description` varchar(100) DEFAULT NULL COMMENT '权限描述', `permission` text COMMENT '权限ID集', `pid` int(2) DEFAULT NULL COMMENT '大类ID 1:平台商-2:采购商-3供应商', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `creator` varchar(30) DEFAULT NULL COMMENT '创建人', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', `modifier` varchar(30) DEFAULT NULL COMMENT '修改人', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=utf8 COMMENT='平台角色权限表
sys_admin:平台管理者表,用于存储平台和供应商管理员,(关联平台角色ID、供应商ID)。平台管理员是预置的,供应商管理员是添加供应商时添加的。
CREATE TABLE `sys_admin` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '权限值ID:自增', `sys_admin_name` varchar(30) NOT NULL COMMENT '管理者名称', `sys_admin_pwd` varchar(32) DEFAULT NULL COMMENT '管理者密码', `cid` int(8) DEFAULT NULL COMMENT '公司ID', `sys_role_id` int(8) DEFAULT NULL COMMENT '平台角色ID', `user_type` int(1) DEFAULT NULL COMMENT '用户固定标签 0:管理员', `icon` varchar(100) DEFAULT NULL COMMENT '头像', `token` varchar(32) DEFAULT NULL COMMENT '登录Token', `login_time` varchar(20) DEFAULT NULL COMMENT '最后登录时间', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `creator` varchar(30) DEFAULT NULL COMMENT '创建人', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', `modifier` varchar(30) DEFAULT NULL COMMENT '修改人', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=310 DEFAULT CHARSET=utf8 COMMENT='平台管理者表'
sysAdiminLogin:后台管理员登录视图SQL
SELECT (CASE`e`.`pid` WHEN '1' THEN '平台管理员' WHEN '3' THEN '供应商管理员' ELSE '' END) AS `user_name`, `a`.`token` AS `token`, `a`.`sys_admin_name` AS `phone`, #登录名 `a`.`sys_admin_pwd` AS `passwd`, #登录密码 `a`.`id` AS `uid`, #管理员ID `a`.`user_type` AS `user_type`, #用户固定标签 0:管理员 1:普通员工 `f`.`customer_name` AS `customer_name`, #公司名称 `f`.`status` AS `status`, #用户状态 0-禁用,1-启用 `f`.`id` AS `cid`, #公司ID `e`.`pid` AS `customer_type`, #大类ID 1-平台商,3-供应商 `e`.`permission` AS `permission`, #权限 `e`.`role_name` AS `role_name` #角色名 FROM `sys_admin` `a` LEFT JOIN `sys_role` `e` ON `a`.`sys_role_id` = `e`.`id` LEFT JOIN `customer_info` `f` ON `a`.`cid` = `f`.`id`
company_role:公司角色权限表,设置公司员工权限 (关联公司ID,该角色属于哪个公司)
CREATE TABLE `company_role` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '权限值ID:自增', `cid` int(8) NOT NULL COMMENT '公司ID', `role_name` varchar(30) NOT NULL COMMENT '权限名称', `description` varchar(100) DEFAULT NULL, `permission` varchar(5000) DEFAULT NULL COMMENT '权限', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `creator` varchar(30) DEFAULT NULL COMMENT '创建人', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', `modifier` varchar(30) DEFAULT NULL COMMENT '修改人', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=179 DEFAULT CHARSET=utf8 COMMENT='公司角色权限表'
company_dept:公司部门表,保存公司部门(关联公司ID,该部门属于哪个公司)
CREATE TABLE `company_dept` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '表ID:自增', `dept_name` varchar(30) NOT NULL COMMENT '部门名称', `pid` int(8) DEFAULT NULL COMMENT '父级部门ID', `cid` int(8) NOT NULL COMMENT '公司ID', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `creator` varchar(30) DEFAULT NULL COMMENT '创建者 id', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', `modifier` varchar(30) DEFAULT NULL COMMENT '修改人', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=181231 DEFAULT CHARSET=utf8 COMMENT='公司部门表'
company_user:公司员工表,(关联公司角色ID,有什么权限;关联公司部门ID,属于哪个部门)
CREATE TABLE `company_user` ( `id` int(8) unsigned NOT NULL AUTO_INCREMENT COMMENT '表ID:自增', `user_name` varchar(30) NOT NULL COMMENT '用户名称', `passwd` varchar(32) NOT NULL COMMENT '登陆密码(MD5加密)', `token` varchar(32) DEFAULT NULL COMMENT '登录Token', `pid` int(8) DEFAULT NULL COMMENT '上级ID', `phone` varchar(30) NOT NULL COMMENT '手机号码', `qq` varchar(20) DEFAULT NULL COMMENT 'qq号', `wechat` varchar(32) DEFAULT NULL COMMENT '微信号', `email` varchar(32) DEFAULT NULL COMMENT '邮箱', `dept_id` int(8) DEFAULT NULL COMMENT '部门ID', `role_id` int(8) NOT NULL COMMENT '角色ID', `user_type` int(1) DEFAULT NULL COMMENT '用户固定标签 1:普通员工', `icon` varchar(100) DEFAULT NULL COMMENT '头像', `view_scope` int(1) DEFAULT '0' COMMENT '查看数据范围(1-本人,2-本部门,3-公司,4,全部)', `status` int(1) DEFAULT NULL COMMENT '员工状态 0-离职,1-在职', `login_time` varchar(20) DEFAULT NULL COMMENT '最新登录时间', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `creator` varchar(30) DEFAULT NULL COMMENT '创建者 id', `modify_time` datetime DEFAULT NULL COMMENT '修改时间', `modifier` varchar(30) DEFAULT NULL COMMENT '修改人', `token2` varchar(32) DEFAULT NULL COMMENT '渠道部APP登录token', `remark` varchar(100) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=233 DEFAULT CHARSET=utf8 COMMENT='公司员工表'
adminLogin:公司员工登录视图
SELECT `a`.`user_name` AS `user_name`, #员工名 `a`.`token` AS `token`, `a`.`passwd` AS `passwd`, #密码 `a`.`phone` AS `phone`, #登录名 `a`.`id` AS `uid`, #员工ID `a`.`user_type` AS `user_type`, #用户固定标签 1:普通员工 `a`.`view_scope` AS `view_scope`, #查看数据范围(1-本人,2-本部门,3-公司,4-全部) `b`.`id` AS `did`, #部门ID `b`.`dept_name` AS `dept_name`, #部门名称 `c`.`id` AS `rid`, #角色ID `c`.`role_name` AS `role_name`, #角色名称 `c`.`permission` AS `permission`, #权限ID集 `e`.`role_name` AS `sys_role_name`, #大类权限名称 `f`.`id` AS `cid`, #所公司ID `f`.`customer_name` AS `customer_name`, #所属公司 `f`.`customer_type` AS `customer_type`, #所属公司类型(1-平台商,3-供应商) `f`.`status` AS `status` #所属公司(供应商)状态 0-禁用,1-启用 FROM `company_user` `a` LEFT JOIN `company_dept` `b`ON `a`.`dept_id` = `b`.`id` LEFT JOIN `company_role` `c` ON `c`.`id` = `a`.`role_id` LEFT JOIN `customer_info` `f` ON `c`.`cid` = `f`.`id` LEFT JOIN `sys_role` `e` ON (`e`.`pid` = `f`.`customer_type` AND `e`.`id` = `f`.`category`) WHERE `a`.`status` = 1
三:权限树格式,role.xml文件,菜单做到二级,功能按钮做到一级
<?xml version="1.0" encoding="UTF8"?> <org> <model name="平台" id="10001" url="/platform"> <menu name="员工管理" id="1000101" url="" icon="employee"> <action id="100010101" name="组织架构" url="/platform/index"> <function id="10001010101" name="组织架构列表"></function> <function id="10001010102" name="添加部门"></function> <function id="10001010103" name="编辑部门"></function> <function id="10001010104" name="删除部门"></function> <function id="10001010105" name="添加员工"></function> <function id="10001010106" name="编辑员工"></function> <function id="10001010107" name="重置密码"></function> <function id="10001010108" name="删除员工"></function> </action> </menu> </model> <model name="客户" id="10002" url="/custom"> <menu name="采购商管理" id="1000201" url="" icon="purchase"> <action id="100020101" name="采购商列表" url="/custom/index"> <function id="10002010101" name="采购商列表"></function> <function id="10002010102" name="添加采购商" url="/custom/addPurchase"></function> <function id="10002010103" name="编辑采购商" url="/custom/addPurchase"></function> <function id="10002010104" name="查看采购商" url="/custom/checkPurchase"></function> <function id="10002010105" name="启用/禁用采购商"></function> <function id="10002010106" name="分配采购商" url="/custom/checkPurchase"></function> <function id="10002010107" name="审核采购商" url="/custom/confirmReview"></function> <function id="10002010108" name="复审采购商" url="/custom/confirmReview"> </function> <function id="10002010109" name="重置密码"></function> </action> </menu> </model> </org>
四:角色权限重要实现
(1)登录接口:localhost:6001/sys/user/adminLogin (参数:手机号,密码)
1.进入滤器,进行签名验证,登录时不需token验证; 2.通过手机号、MD5(密码)作为参数获取登录信息,(管理员->sysAdiminLogin视图,普通员工->adminLogin视图); 3.若拿到登录信息,数据验证(如部门、角色、权限、禁用等),清除缓存老的token; 4.用户名+公司名+手机号+当前时间,MD5双重加密生成新token; 5.改变最新登录时间,缓存添加新token,设置有效时间为1小时; 6.更新数据库对应登陆者的token、最新登录时间; 7.登录成功返回token,用户信息(去除密码)。
token验证及redis缓冲延时:
1.根据指定前缀+token作为key,从redis获取登录信息userInfo;
2.若拿到userIfon,如果缓存有效时间小于10分钟将更新缓存;
3.以relogin为键将userInfo放到session中,然后放行。
(2)获取用户对应菜单信息:localhost:6001/sys/sysRole/getMenuByRoleId
目的:展示对应的模块和菜单
1.从session获取登录信息,拿到用户角色对应逗号拼接功能权限ids;
2.循环拿到每个功能id遍历role.xml找到对应元素及所有上级元素封装到List<SysRoleVO> list;
3.上面的list会存在多个重复的功能上级元素,重写SysRoleVO的equals方法(name、id都相同),通过contains方法判断去重;
4.找到所有的一级节点,为一级节点设置子菜单(递归,继续为子菜单添加子菜单)返回。
( 3)平台用户类型、角色管理权限树:localhost:6001/sys/sysRole/getRolePermission ,localhost:6001/sys/role/getRolePermission
目的:为用户类型-角色授权做准备
1.通过角色roleId获取逗号拼接功能权限ids;
2.new SAXReader().read(is)加载role.xml权限树,将所有元素封装到List<RoleVO> list,RoleVO所有auth属性值均为false; 3.循环list,ids改变auth属性值为true或false;4.找到所有的一级节点,为一级节点设置子菜单(递归,继续为子菜单添加子菜单)返回。
( 4)供应商管理员及供应商员工,角色权限树-->localhost:6001/sys/role/getRolePermission 注:最多只能看到平台为该供应商管理员分配的权限菜单
1.从session获取登录信息,拿到管理员逗号拼接功能权限ids; 2.根据角色ID获取角色对应权限ds2; 3.遍历ids拿到每个id去匹配role.xml,将部分元素封装到list<RoleVo> list,同时便利ids2比较是否相等,改变auth属性值为true或false; 4.去重,递归分配子菜单。
五:组织架构重要实现
(1)获取组织架构树结构:http://192.168.99.131:6001/sys/dept/findDeptByCid
1.根据公司ID找到所有的部门List<CompanyDeptVo> rootDepartment ;
2.遍历rootDepartment拿到所有的一级部门了,一级菜单没有parentId;
3.为一级菜单递归设置子菜单,同时统计一级菜单所拥有的员工数(含子部门员工);
(3)获取员工列表:http://192.168.99.131:6001/sys/user/findUserByParm
1.通过部门ID参数查询所属部门id集合;2.通过部门Id集合过滤员工;