JWT登录鉴权 axios封装动态路由跳转成功

该文描述了一个Vue应用中使用拦截器处理token保存与请求头设置的过程,包括密码验证规则,利用JSONWebToken解码获取用户信息。同时,文章提到了全局Loading的实现,以及Vuex状态管理中用户登录状态的维护,包括刷新页面后的处理和路由拦截确保登录状态。此外,还涉及了动态加载菜单的逻辑和处理token失效的情况。
摘要由CSDN通过智能技术生成

使用拦截器,保存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下的代码更简单

axios报错

路由钩子处理登录状态
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];
    })
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值