1. 用户登录实现
1.1 动态生成密钥
@Override
public String findUserByUP(User user) {
byte[] bytes = user.getPassword().getBytes();
String md5Pass = DigestUtils.md5DigestAsHex(bytes);
user.setPassword(md5Pass);
User userDB = userMapper.findUserByUP(user);
if(userDB == null) {
return null;
}
// String token = "密钥";
return UUID.randomUUID().toString().replace("-", "");
}
1.2 关闭IDEA 中Mapper错误提示
1.3 前端jS
login(){
//获取表单对象之后进行数据校验
//valid 表示校验的结果 true表示通过 false表示失败
this.$refs.loginFormRef.validate(async valid => {
//如果没有完成校验则直接返回
if(!valid) return
//如果校验成功,则发起ajax请求
const {data: result} = await this.$http.post('/user/login',this.loginForm)
//console.log(result)
//{"status":200,"msg":"服务器调用成功!","data":"9dabfec582754e7ebaaf981f5f09042a"}
if(result.status !== 200) return this.$message.error("用户登录失败")
this.$message.success("用户登陆成功")
//获取用户token信息
let token = result.data
window.sessionStorage.setItem("token",token)
//用户登录成功之后,跳转到home页面
this.$router.push("/home")
})
}
1.4 Cookie 和 Session
1.4.1 业务说明
将服务器数据持久化
1.4.2 Session 的概念
- Session称为“会话控制"
- Session可以存储用户信息.
- Session数据的生命周期是整个会话,如果会话关闭 则数据清空.
- Session的数据结构 是key-value结构.
- 浏览器Session存储的位置
1.4.3 Cookie 说明
- Cookie 是一个小型文本文件,存储在本地终端上
- Cookie 也可以存储用户信息
- Cookie 的数据类型key - value
- Cookie 中的数据一般采用加密的方式保存
- Cookie 的数据可以永久保存
1.4.4 Session 和 Cookie 选择
特点:
1. 如果数据需要临时保存,则选用Session,如果数据需要长时间存储选用Cookie
2. 如果对于安全性要求较高的数据,选用Session,如果安全性要求不高,选用Cookie
1.4.5 用户登录实现数据存储
//获取用户token信息
let token = result.data
window.sessionStorage.setItem("token",token)
1.5 实现系统首页跳转
1.5.1 需求说明
用户完成登录之后,系统跳转首页
1.5.2 编辑路由
import Home from '../components/Home.vue'
const routes = [
{path: '/', redirect: '/login'},
{path: '/login', component: Login},
{path: '/elementUI', component: ElementUI},
{path: '/home', component: Home}
]
//用户登录成功之后,跳转到home页面
this.$router.push("/home")
1.6 Vue 路由导航
1.6.1 路由概念
1.6.2 Vue路由组件
1.6.3 业务需求
前端进行权限校验,防止未登录用户访问其他页面
校验规则:
1. 没有token信息,用户跳转到登录页面
2. 如何才能实现每一次的请求都要校验
解决方案:拦截器
1.6.4 路由导航守卫(拦截器)
/**
* 路由导航守卫实现
* beforeEach用户的每次请求在访问目标网址之前都被拦截
* 参数:
* 1. to 用户请求的网址对象
* 2. from 用户请求的来源
* 3. next 请求的放行
* 需求:
* 1. 如果用户访问登录页面
* 2. 校验是否含有token数据
* 有token 放行
* 没有token 跳转到登录页面
*/
// router.beforeEach(function(arg){
// })
router.beforeEach((to, from, next) => {
console.log(to)
console.log(from)
if(to.path === '/login'){
//直接跳转并且结束代码
return next()
}
//2. 判断是否有token
let token = window.sessionStorage.getItem("token");
if(token !== null){
return next()
}
next('/login')
})
2. 左侧菜单列表实现
2.1 代码结构
2.2 业务接口
http://localhost:8091/rights/getRightsList
{
"status": 200,
"msg": "服务器调用成功!",
"data": [
{
"created": "2021-02-18T11:17:23.000+00:00",
"updated": "2021-02-18T11:17:23.000+00:00",
"id": 1,
"name": "用户管理",
"parentId": 0,
"path": null,
"level": 1,
"children": [
{
"created": "2021-02-18T11:22:19.000+00:00",
"updated": "2021-02-18T11:22:19.000+00:00",
"id": 2,
"name": "用户列表",
"parentId": 1,
"path": "/user",
"level": 2,
"children": null
}
]
},
{
"created": "2021-02-18T11:22:41.000+00:00",
"updated": "2021-02-18T11:22:41.000+00:00",
"id": 3,
"name": "商品管理",
"parentId": 0,
"path": null,
"level": 1,
"children": [
{
"created": "2021-02-18T11:23:12.000+00:00",
"updated": "2021-02-18T11:23:12.000+00:00",
"id": 4,
"name": "商品列表",
"parentId": 3,
"path": "/item",
"level": 2,
"children": null
},
{
"created": "2021-02-18T11:25:00.000+00:00",
"updated": "2021-02-18T11:25:00.000+00:00",
"id": 6,
"name": "商品分类",
"parentId": 3,
"path": "/itemCat",
"level": 2,
"children": null
}
]
},
{
"created": "2021-02-18T11:23:44.000+00:00",
"updated": "2021-02-18T11:23:44.000+00:00",
"id": 7,
"name": "权限管理",
"parentId": 0,
"path": "",
"level": 1,
"children": [
{
"created": "2021-02-18T11:24:12.000+00:00",
"updated": "2021-02-18T11:24:12.000+00:00",
"id": 9,
"name": "权限列表",
"parentId": 7,
"path": "/rights",
"level": 2,
"children": null
},
{
"created": "2021-02-18T11:24:12.000+00:00",
"updated": "2021-02-18T11:24:12.000+00:00",
"id": 10,
"name": "角色列表",
"parentId": 7,
"path": "/role",
"level": 2,
"children": null
}
]
},
{
"created": "2021-02-18T11:24:12.000+00:00",
"updated": "2021-02-18T11:24:12.000+00:00",
"id": 8,
"name": "数据统计",
"parentId": 0,
"path": null,
"level": 1,
"children": [
{
"created": "2021-02-18T11:24:12.000+00:00",
"updated": "2021-02-18T11:24:12.000+00:00",
"id": 15,
"name": "统计报表",
"parentId": 8,
"path": "/report",
"level": 2,
"children": null
}
]
}
]
}
2.3 权限列表查询SQL
select p.id,p.name,p.parent_id,p.path,p.level,p.created,p.updated,c.id c_id,c.name c_name,c.parent_id c_parent_id,c.path c_path,c.level c_level,c.created c_created,c.updated c_updated from
(select * from rights where parent_id=0) p
left join
rights c
on p.id = c.parent_id
2.4 前端页面JS分析
- 生命周期函数
//初始化函数
created() {
//动态获取左侧菜单信息
this.getMenuList()
//设定模式选中按钮
this.defaultActive = window.sessionStorage.getItem("activeMenu")
},
- 获取远程服务器数据
async getMenuList() {
const {data: result} = await this.$http.get('/rights/getRightsList')
if(result.status !== 200) return this.$message.error("左侧菜单查询失败")
this.menuList = result.data
},
2.5 后端实现
2.5.1 Controller
/**
* 业务说明: 完成菜单列表查询 1-2级
* URL:/rights/getRightsList
* 返回值: SysResult(List)
*/
@GetMapping("/getRightsList")
public SysResult getRightsList() {
List<Rights> list = rightsService.getRightsList();
return SysResult.success(list);
}
2.5.2 Mapper 映射文件
<select id="getRightsList" resultMap="rightsRM">
select p.id,p.name,p.parent_id,p.path,p.level,p.created,p.updated,
c.id c_id,c.name c_name,c.parent_id c_parent_id,c.path c_path,c.level c_level,c.created c_created,c.updated c_updated
from
(select * from rights where parent_id=0) p
left join
rights c
on p.id = c.parent_id
</select>
<resultMap id="rightsRM" type="Rights" autoMapping="true">
<id property="id" column="id"></id>
<!-- 封装一对多数据 -->
<collection property="children" ofType="Rights">
<id property="id" column="c_id"></id>
<result property="name" column="c_name" />
<result property="parentId" column="c_parentId" />
<result property="path" column="c_path" />
<result property="level" column="c_level" />
<result property="created" column="c_created" />
<result property="updated" column="c_updated" />
</collection>
</resultMap>
2.6 利用Mybatis子查询的方式获取数据(扩展)
2.6.1 SQL语句
select * from rights where parent_id=0
select * from rights where parent_id=1
2.6.2 Mapper 映射代码
<!--子查询方式获取菜单-->
<select id="getRightsList2" resultMap="childrenRM">
select * from rights where parent_id=0
</select>
<resultMap id="childrenRM" type="Rights" autoMapping="true">
<id property="id" column="id"></id>
<!--一对多封装 column 在子查询的条件中传递的参数-->
<collection property="children" ofType="Rights" select="selectRightsByParentId" column="id"></collection>
</resultMap>
<!--单表查询子数据-->
<select id="selectRightsByParentId" resultType="Rights">
select * from rights where parent_id=#{id}
</select>