使用拦截器,保存token,获取token并保存在请求头
// 拦截器的处理
instance.interceptors.request.use(config => {
const token = window.sessionStorage.getItem('token');
console.log(config);
if(token) {
// 挂载到请求头
config.headers.token = token;
}
return config;
},err => {});
instance.interceptors.response.use((response) => {
// 保存token
const token = response.data.data.token;
console.log(response);
if(token) {
window.sessionStorage.setItem('token',token)
}
return response;
},err=>{})
密码验证函数:不能小于6,不能为空
var validatePass = (rule,value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else if (value.length < 6) {
callback(new Error('密码长度不能小于6'));
} else {
callback();
}
};
pass: [
{ validator:validatePass, trigger: 'blur' }
],
jsonweb 解密 token,获取数据
import jwt from 'jsonwebtoken'
let userInfo ;
if(res?.data?.data?.token) {
userInfo = jwt.decode(res.data.data.token,'jindu520');
}
其中
exp 过期的毫秒数
iat:是创建时间
全局Loading
import { Loading } from "element-ui";
loadingInstance = Loading.service({fullscreen:true});
loadingInstance.close();
整理代码:
把拦截器写在utils下的request.js里面
export const request = Axios.create({
baseURL:'/api'
})
let loadingInstance;
// 拦截器的处理
request.interceptors.request.use(config => {
const token = window.sessionStorage.getItem('token');
console.log(config);
// 全局loading
loadingInstance = Loading.service({fullscreen:true});
if(token) {
// 挂载到请求头
config.headers.token = token;
}
return config;
},err => {
});
request.interceptors.response.use((response) => {
loadingInstance.close();
// 保存token
const token = response.data.data.token;
console.log(response);
if(token) {
window.sessionStorage.setItem('token',token)
}
// 603 token失效
return response;
},err => {
// 系统异常处理,也可做错误日志收集
return Promise.reject(err);
})
把res提取出来放入apis下的user.js里面
port { request } from "../utils/request"
export const doLogin = (user)=> {
return request.post("/user/login",{
account:user.username,
password:user.pass
});
Login.vue
let res = await doLogin(form);
if (res.data.code === 20000) {
let userInfo;
if (res?.data?.data?.token) {
userInfo = jwt.decode(res.data.data.token, 'jindu520');
// 改变用户信息
this.changeUserInfo({
username: userInfo.account
});}
this.changeLogin(true)
this.$router.push('/')
} else {
alert('登录失败')
}
调整后Login.vue下的代码更简单
路由钩子处理登录状态
index.js
router.beforeEach((to,from,next) => {
// login /register 需要验证吗? => 白名单 放行
// 非白名单 => 2.1 是否登录 => 登录了,token中解码,2.3 登录了角色菜单,
=> 没有登录,去login登录
next();
})
conf.js
export const whiteUrlList = ['/login']
index.js
if(whiteUrlList.includes(to.path)) {
return next();
}
非白名单
index.js
import {checkLogin} from '@/utils/index'
if(checkLogin()){
}
utils下的index.js
import jwt from 'jsonwebtoken'
import {secure} from '@/conf'
export const checkLogin = () => {
const token = getToken();
if(!token) return null;
return jwt.decode(token,secure); //token解码
}
export const getToken = () => {
return window.sessionStorage.getIten('token') // 保存token
}
conf
export const secure = 'jindu520'
index.js
let userInfo = checkLogin();
if(userInfo) {
} else {
next('/login?redirect=' + to.path) // 没登陆让他登录
}
Login.vue
this.$route.push(this.$route.query.redirect || "/")
重定向跳转不了,不清楚原因,不管了
store下的modules的user.js
getUserMenus(state) {
return state.userMenus;
}
changeMenus(state,payload) {
state.userMenus = payload;
}
解决刷新后vuex中没有保存用户信息的问题
router下的index
import store '@/store'
if( !store.getters['user/getUserInfo']) {
store.commit('user/changeUserInfo',{
username:userInfo.account
});
store.commit(''user/changeIsLogin",true)
}
没解决前,一刷新,vuex中就没有用户登录信息了
解决后,用户信息没有变动
刷新导致路由没有了
router index.js
if(!store.getters['user/getUserMenus']) {
return loadMenus()
}else {
return next();
}
loadMenus
注释main.js
Axios.defaults.baseURL='/api' // 访问public下的menus
router下的index.js
loadMenus
import Axios from 'axios'
import { pretty } from '@/utils/request'
async function loadMenu(next,to) {
let [res,err] = await pretty(Axios.get('/menus.json'));
if(err) {
throw new Error('加载动态菜单出错' + err.message);
}
}
menu.json 改变内容
"redirect":"/home",
"component":"Layout"
"children" : [
{ "path":"/home",
"component": " Home"
}
]
router下的index.js
改路由名字为constantRoutes,放入routes上
let asyncRoutes = asyncRoutesHandler(res.data);```
router.addRoutes() //加异步路由,但是废弃了
asyncRoutes.forEach(r=> {
router.addRoute(r)
})
router.addRoute(r)
// next()
import Layout from '@/layouts/Layout'
function asyncRoutesHandler(routes) {
return routes.map(r=>{
if(r.component === 'Layout') {
r.component = Layout;
} else {
const filePath = r.component;
r.component =() => import(`../views/${filePath}.vue`)
}
if(r.children) {
r.children = asyncRoutesHandler(r.children);
}
return r;
})}
新建一个layouts文件夹,再建一个Layout
<template>
<div>
局部组件,动态内容
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'Layout'
}
</script>
<style>
</style>
router下的index.js loadMenu函数
store.commit('user/changeUserMenus',res.data);
next({...to,replace: true}) // 替换当前访问的路径,不会有多余上一页的箭头
603导致的token失效问题,
改一下
http://localhost:8081/menus.json
pretty 在request上写
export const pretty = function(promise) {
return promise.then(data => {
return [data,undefined];
})
.catch(err => {
[undefined,err];
})
}