一、前端流程分析
若依前端的登录流程主要涉及以下代码:
- permission.js
- views/login.vue
- utils/request.js 会在请求 header 里,携带 token
- utils/auth.js 用来管理 cookie 中的 token
- store/modules/user.js 用户状态数据管理,发起对后台的访问,并处理返回数据
- store/modules/permission.js 路由状态数据管理
主要逻辑都在 src/permission.js 中,里面实现的是一个路由 router 的拦截器,
大体步骤如下:
1、每次客户发起访问请求,都会先检查客户端,看是否在 cookie 中保存了 Token
if (getToken())
没有则检查白名单,最后,跳转到 /login
2、访问非 /login 路径,会检查状态管理器 store/modules/user.js 中是否缓存了用户角色
if (useUserStore().roles.length === 0) { isRelogin.show = true // 判断当前用户是否已拉取完user_info信息 useUserStore().getInfo().then(() => { isRelogin.show = false usePermissionStore().generateRoutes().then(accessRoutes => { // 根据roles权限生成可访问的路由表
没有则通过store/modules/user.js 对后台发起请求 /getInfo,重新获取用户 roles,
然后再通过store/modules/permission.js 发起请求 /getRouters,获取路由(菜单)信息
3、在发起 /getInfo 请求后,后台可能返回两种情况:
- 返回 http 错误,错误码 4xx 、5xx ,则跳转到 /logout
- 如果不是 http 错误,而是由后台封装异常代码到 response.data.code 中,这会被 request.js 中的 response 拦截器给拦截到
// 响应拦截器service.interceptors.response.use(res => { // 未设置状态码则默认成功状态 const code = res.data.code || 200; // 获取错误信息 const msg = errorCode[code] || res.data.msg || errorCode['default'] console.log('code=',code,'msg =',msg); // 二进制数据则直接返回 if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){ return res.data } if (code === 401) { console.log('get 401') if (!isRelogin.show) { isRelogin.show = true;
(这种拦截器的模式,虽然让写代码的很爽,但是让看代码的真的很累)
4、views/login.vue 登录 handleLogin() 成功后,也会跳转进入上面的流程(因为 permission.js 拦截所有路由访问)
// 调用action的登录方法 userStore.login(loginForm.value).then(() => { router.push({ path: redirect.value || "/" }); }).catch(() => {
注意:前端关闭页面或者刷新页面时,状态管理器中的数据会消失,但是 cookie 保存的数据会一直在的
总结一下:
前端登录过程会对后端发起三个请求(让我想起了阿拉丁):
- /login
- /getInfo
- /getRouters
非登录情况下,会在请求头中,携带 token
if (getToken() && !isToken) { config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 }
下次分析后台时,再讨论具体的数据结构。