router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import jwt_decode from "jwt-decode";
const WHITE_LIST = ['/login']
const routes = [
{
path: '/',
component: () => import("@/App.vue"),
redirect: "/login",
children: [{
path: '/login',
name: 'login',
component: () => import("@/views/login/index.vue")
}, {
path: '/test',
name: 'test',
component: () => import("@/views/test/index.vue")
}]
},
]
const router = createRouter({
history: createWebHistory(), //history
routes
})
// 路由守卫
router.beforeEach((to, from, next) => {
let token = localStorage.getItem("token");
if (token) {
// 前端判断token是否过期
if (jwt_decode(token).exp < parseInt(new Date().getTime() / 1000)) {
ElMessage.warning("登录状态已过期, 请重新登录")
localStorage.clear();
next({
path: '/login',
query: to.path === '/' ? {} : { from: to.path }
});
} else {
next();
}
}
else if (WHITE_LIST.includes(to.path)) {
next();
}
else {
next({
path: '/login',
query: to.path === '/' ? {} : { from: to.path }
});
}
});
export default router
src/utils/axios.js:
/**
* axios实例
*/
import axios from 'axios';
const service = axios.create({
// baseURL: `http://${config_settings.host}:${config_settings.port_node}`
baseURL: `/api`
});
service.defaults.timeout = 1000 * 60
/* 添加请求拦截器 */
service.interceptors.request.use(
(config) => {
// 添加token到header
const token = localStorage.getItem('token');
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
/* 添加响应拦截器 */
service.interceptors.response.use((res) => {
return res;
},
error => {
return Promise.reject(error);
});
export default service;
src/view/login/index.vue:
<!--登录页 login-->
<template>
<div class='login'>
<el-form ref="formData" :model="state.formData" :rules="state.rules" label-width="80px">
<el-form-item prop="username" label="用户名">
<el-input v-model="state.formData.username" placeholder="请输入用户名" prefix-icon="icon-login_user"
clearable>
</el-input>
</el-form-item>
<el-form-item prop="password" label="密码">
<el-input v-model="state.formData.password" placeholder="请输入密码" type="password"
prefix-icon="icon-login_pwd" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" class="btn" @click="login()" icon="el-icon-upload">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import axios from '@/utils/axios';
import { useRoute, useRouter } from 'vue-router';
const router = useRouter();
const state = reactive({
formData: {
username: 'admin',
password: 'admin',
},
rules: {
username: [{ required: true, message: '用户名不能为空', trigger: 'blur' }],
password: [{ required: true, message: '密码不能为空', trigger: 'blur' }],
}
})
const login = async () => {
let { data } = await axios.post('/login', {
username: state.formData.username,
password: state.formData.password
})
console.log("data:", data)
if (data.code == 0) {
localStorage.setItem("token", data.token);
router.push('/test');
ElMessage({ message: '登录成功', type: 'success' });
} else {
ElMessage({ message: '登录失败', type: 'success' });
}
}
computed(() => {
})
onBeforeMount(() => {
})
onMounted(() => {
})
</script>
<style lang="scss" scoped>
.login {}
</style>
后端代码见:https://gitee.com/LiDaJiang/git_koa2https://gitee.com/LiDaJiang/git_koa2