开发基于RBAC的权限控制模块
◆基于角色权限控制(RBAC)是面向企业安全策略的访问控制方式
◆RBAC核心思想是将控制访问的资源与角色(Role)进行绑定
◆系统的用户(User)与角色(Role)再进行绑定,用户便拥有对应权限
RBAC底层设计
打开navicat数据库,,选择imooc_oa数据库,点击查询,新建查询,将sql文件夹下的sql文件源代码复制粘贴,sql表就创建成功了
为了统一规范,防止主键外键类型不统一关联查询出现问题,所以牺牲空间,设置为bigint
分析各张表:
初识Element Plus
网站快速成型工具
Elment Plus,一套为开发者、设计师和产品经理准备的基于Vue3.0的桌面端组件库
一个 Vue 3 UI 框架 | Element Plus (gitee.io)
后端工程师推荐使用CDN方式进行安装,详细请查询官方文档
Element Plus依托于Vue组件,所以需要导入Vue插件
在webapp目录下新建assets文件夹,里面存放css、js、html等前端代码进行统一管理
首先新建vue文件夹,将学习vue3.0时的vue.global.js文件直接粘贴放入
还有Element Plus的资源目录也直接粘贴放入,还有axios.js文件
实现登陆功能
在webapp目录下新建login.html文件
el-form等标签是Element Plus组件里的特定标签
逗号写在前面便于注释和维护,不用再删上一个后面的逗号
Form 表单 | Element Plus (gitee.io)
输入localhost/login.html
<el-input type="password" placeholder="请输入密码" v-model="form.password"></el-input>
中把 type="text"
改为 type="password"
就可以密码输入时变成*号
实现用户登陆model层
为了便于测试,数据库添加test用户
记得提交事务,才保存成功
创建子包com.imooc.oa.entity,用于存储数据库的一个个对象
新建User.java类
属性与数据库字段一一对应,已经开启驼峰命名转换
快速生成get、set以及toString方法
接下来为其添加sql语句配置
在resource→mappers文件夹下添加user.xml文件
*获取的数据库字段会自动驼峰命名转换向User对象进行赋值
写完后一定要记得在mabatis-config.xml进行注册配置让其知道User.xml文件的存在
我们在讲解到MVC模式的时候需要两个类,一个是service类,一个是mapper类
新建这两个包
其中mapper下新建UserMapper.java,用于处理数据库的增删改查
usermapper.selectByUsername
对应上面user.xml里的命名空间+id的访问方式
我们发现mapper不实现业务逻辑,只是纯粹用于数据库增删改查,具体实现要追溯到上一级service文件夹
新建UserService.java文件
java没有提供登录失败异常,需要我们自己创建
在service下创建子包exception,名为LoginException.java
需要继承RuntimeException
运行时异常然后进行单元用例测试
右键类名,点击code→gnerate→Test
实现用户登陆Controller层
如何在web应用中对外暴露数据?不再是业务逻辑负责范畴,需要Controller层承上启下,主要实现的组件是Servlet
oa包下创建controller控制层包,新建LoginServlet.java
使用@webServlet()绑定url,为了统一工程接口,使用/api/的方式,application/json
前台向servlet发起请求,返回的是json格式文件。所以没用text的格式
绝大部分控制层要做的三件事:
- 接收用户输入
- 调用业务逻辑
- 返回JSON结果
返回json结果需要导入依赖
tomcat发布时,默认不会将我们导入的依赖发布到webapp下,所以可能会报错误,需要我们在项目结构在工件下选中所有jar包,右键添加到lib目录下
既然服务器能返回错误信息,如何在错误信息中返回登陆用户名
在try语句块中添加data数据项
如果删掉password,会报密码错误
同理username报用户名不存在
实现用户登录View层
login.html是view层,主要作用是提交数据,如何和后台进行交互,需要通过axios组件使用ajax通过异步方式进行通信
继续添加
json.code=="0"
表示处理成功,进入后台首页
const $message = this.$message;
可以帮我们生成好看的错误提示等对话框
message:json.message
是从json获取到的错误数据
如输错密码:
输错用户名:
封装ResponseUtils工具
对一些小细节进行优化,比如(“code”,0)这些标准化数据,可以封装,减少后续重复处理
在utils包下创建ResponseUtils.java类
其中添加put方法目的完全为了便于我们进行测试用例
首先选中函数名
然后菜单栏生成测试用例:code→gernerate→Test
想要设置等多个附加data数据只需继续.put即可
toJsonString()
方法转为json对象
put2()方法是对put1()的简写
然后右键函数名进行运行
这种情况请先点击maven生命周期的clean命令,即可重新运行成功
那么LoginServlet.java如何修改呢
我们只在后台进行了json逻辑调整,没有对这个页面进行任何修改,只关心返回数据和提交地址,服务端做了什么变换对于这个界面没有任何影响,这就是mvc一大优势,使前端实现和后端逻辑进行了解耦
封装Md5Utils加密工具类
密码通过原文保存,为了防止泄露,使用Md5加密
MD5摘要算法
◆MD5信息摘要算法是广泛使用的密码散列函数
◆MD5可以产生出一个128位的散列值用于唯一标识源数据
◆项目中通常使用MD5作为敏感数据的加密算法
MD5在线加密 (hwcha.com)
- 即使拿到加密后的字符串,也不会得到原密码,操作不可逆
- 原密码不修改加密多少次都不会改变md5,修改原密码一两位数字生成的md5没有规律,强绑定
- 无论加密前字符串多长,加密后md5长度稳定
Apache Commons Codec
◆Commons-Codec是Apache提供的编码/解码组件
◆通过Commons-Codec可轻易生成源数据的MD5摘要
◆MD5摘要方法:String md5=DigestUtils.md5Hex(源数据)
Codec – Home (apache.org)
这是阿帕奇提供的开源md5加密解密项目
pom.xml增加依赖:
记住,重新加载后,还要再项目结构→工件,将依赖右键添加到WEB-INF的lib目录下,才能在发布环境使用它
新增工具类Md5Utils.java
进行测试
md5在线解密破解,md5解密加密 (cmd5.com)
仍旧就不安全,不是不可逆吗,为何还能反推?
因为此网站使用穷举法,由于md5特殊性,原密码不修改加密多少次都不会改变md5,所以将常见密码和对应的md5加密保存到数据库,只是做了反向查询而已
所以我们只需要在原密码上动手脚,比如变复杂,搞特殊符号,就不会被反向查询到了,在加密过程称为加盐
完整登陆功能实现
查看我们数据库数据,password部分是通过md5+盐值的方式进行保存
然后在UserService.java下修改
在UserServiceTest.java进行测试,测试成功(m8用户名对应密码是test)
如果运行checkLogin3()会报密码错误
调整好UserService后,LoginServlet.java不用调整,包裹前端页面Login.html也不需要调整
重新运行输入用户名m8,密码test,就能成功跳转到index.html首页了
此时还有个问题,当黑客进行抓包时可以获取到链接,导致md5和盐值salt泄露,所以我们需要将其隐藏
在LoginServlet.java文件try语句块添加语句块
将favvicon.ico文件直接复制粘贴到webapp目录下,可以直接为网页导航栏添加图片
到此登陆界面算是开发完毕了
绘制后台首页UI布局
在webapp下新建index.html
查看常用布局页面
Container 布局容器 | Element Plus (gitee.io)
注意需要设置下面代码段,才能全屏显示不同区域
iframe标签中src可以设置网页,包括自己的URI网页,调用自己书写的,如果设置为height:100%,右侧会出现小滚动条,不美观,所以设置为95%
开发RBACModel层
首先先来开发功能区
首先分析数据库
sys_user(user_id)→sys_role_user(role_id)→sys_role_node(node_id)→sys_node(node_name)
从登陆角色表中(sys_user)获取到user_id,然后根据角色权限功能表中(sys_node)获得功能node_name
使用多表查询功能
新建查询
看出1号员工对应功能为这四项
改变ru.user_id = 1
中数值,数值从角色登陆表获得,就可以得到不同权限下的功能
我们使用sql传参方式进行选择user_id
在resources资源目录下的mappers新建rbac.xml文件,进行sql语句的配置书写
在com.imooc.oa.entity下创建实体类Node.java对sql执行结果进行保存接收
写好rbac后不要忘记在mybatis-config文件下进行注册
然后在com.imooc.oa.mapper下新建RbacMapper.java,用于执行sql语句
向上推演,在com.imooc.service下新建RbacService.java用于处理用户权限
然后我们进行测试
注意3后面加l表示长整型,我们parameterType="Long"
为长整型
行政审批下对应这两个功能
开发RBAC Contronller层
我们模块下分有很多功能,上面行政审批下对应两个功能,我们要像右边一样有层次展现
node_type表示等级,1表示模块名,2表示功能名
在contronller下新建UserInfoServlet.java,用来获取与用户相关信息,其中包括用户所拥有相关功能
重启tomcat,访问localhost/api/user_info?uid=3
开发RBAC View层
我们请求的uid如何与前台进行交互?
在login.html中,在登陆前将关键信息保存,比如用户编号,才能进行后续处理查看系统功能有哪些
login.html中
重新运行,会话成功存储,如果关闭页面窗口,就会销毁,会话存储与页面窗口绑定,而本地存储不会,我们根据需求进行选择存储,现在登陆界面只需要短期存储
修改index里的script标签块
通过ajax向nodeList:[]异步发送数据
访问http://localhost/index.html
可以看出成功打印出json信息,那该如何显示在功能区呢?
element plus早已为我们准备好了
Menu 菜单 | Element Plus (gitee.io)
在index.html文件下的e-aside标签对里添加代码
为了点击跳转url,使用showpage方法,在method里添加
回顾Mapper接口开发过程
修改页面header部分
用户名和职位我们都是写死的,如何动态进行修改?我们重新回顾下开发过程
sql文件夹添加有employee数据文件
复制下代码到那navicat进行使用,新建查询并运行
老规矩,先创建实体类,在entity下,新建Employee.java
接下来在资源目录mappers文件夹下书写eployee.xml
此时命名空间不能随便写了,需要使用接com.imooc.oa.mapper.EmployeeMapper
EmployeeMapper等会写
在java下创建接口com.imooc.oa.mapper.EmployeeMapper
selectById
名字要和eployee.xml下的id属性对应
不要忘记在mybatis-config.xml注册
然后进行测试用例
上面就是基于Mapper接口进行数据查询
接下来就是将其继续开发,完成header部分的动态处理
在service下创建EployeeService.java
写好service后,根据MVC的反顺序,向上推进找到controller层
记住,我们编程逻辑顺序从先获取数据库的底层反着来,根据MVC的四个步骤进行
在UserInfoServlet.java中,用于获取与用户相关信息,其中包含员工数据
先实例化employee
再按员工编号获取数据,doGet方法里添加获取员工编号
然后带到selectById()方法中
得到了员工数据,通过ResponseUtils返回给客户端,只需额外增加put方法即可
这样当前登陆员工获取到了
验证一下localhost/api/user_info?uid=1&eid=1
数据获取成功,如何和界面进行绑定?
打开login.html登录页
这里存放了eid,我们在index.html进行提取
在.mount(){}进行事件绑定
在哪用?要和当前数据进行绑定,在data(){}数据块中
这样employee:{}里就有数据了
后面进行双向绑定
将张三[研发工程师]进行修改,动态实现绑定
修改为
更新tomcat的类和资源
然后登陆账号m8,密码test,进入成功
查看数据库
通过employ_id对应上m8
接下来设置注销逻辑,先绑定注销事件
处理注销方法
sessionStorage.clear();
表示清空登陆数据,然后跳回登陆页面