路由攔截
項目中,有些頁面需要登錄后才能進入,例如,在某頁面A,用戶在操作前需要先進入登錄頁(此時需要將上一頁的地址(/survey/start)作為query存入login頁面的地址中,如: http://localhost:8071/#/login?redirect=%2Fsurvey%2Freport),登錄成功后再進入頁面A。
首先,在router.js中創建路由時,給需要登錄的路由中的 meta 添加字段:requireLogin,如下:
const router = new Router({
routes: [
{
path: '/login',
name: 'Login',
component: Login,
meta: {
title: '登錄頁'
}
},
{
path: '/register',
name: 'Register',
component: Register,
meta: {
title: '注冊頁'
}
},
{
path: '/',
redirect: '/survey/start',
name: 'Full',
component: Full,
children: [
{
path: '/survey/start',
name: 'Home',
component: Home,
meta: {
title: '首頁',
requireLogin: true
}
},
{
path: '/survey/report',
name: 'Report',
component: Report,
meta: {
title: '詳情頁',
requireLogin: true
}
}
]
}
]
})
然后使用 router.beforeEach 注冊一個全局前置守衛:
// 全局導航鈎子
router.beforeEach((to, from, next) => {
if (to.meta.title) { // 路由發生變化修改頁面title
document.title = to.meta.title
}
if (to.meta.requireLogin) {
if (store.state.token) {
if (Object.keys(from.query).length === 0) { // 判斷路由來源是否有query,處理不是目的跳轉的情況
next()
} else {
let redirect = from.query.redirect // 如果來源路由有query
if (to.path === redirect) { // 避免 next 無限循環
next()
} else {
next({ path: redirect }) // 跳轉到目的路由
}
}
} else {
next({
path: '/login',
query: { redirect: to.fullPath } // 將跳轉的路由path作為參數,登錄成功后跳轉到該路由
})
}
} else {
next()
}
})
關於Vue Router導航守衛,參考:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB
axios 請求攔截
上面的方法只是進行了前端攔截,無法確定存儲在本地的token是否已經失效。需要 axios 攔截器:
在mian.js 中:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Axios from 'axios'
import './assets/styles/reset.css'
import './plugins/element.js'
import htmlToPdf from './utils/htmlToPdf'
Vue.config.productionTip = false
Vue.use(htmlToPdf)
// http request 攔截器
Axios.interceptors.request.use(
config => {
if (sessionStorage.getItem('token')) { // 若存在token,則每個Http Header都加上token
config.headers.Authorization = `token ${sessionStorage.getItem('token')}`
}
return config;
},
err => {
return Promise.reject(err);
})
// http response 攔截器
Axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 返回 401 (未授權) 清除 token 並跳轉到登錄頁面
sessionStorage.removeItem('token')
router.replace({
path: 'login',
query: {
redirect: router.currentRoute.fullPath
}
})
}
}
return Promise.reject(error.response.data) // 返回接口返回的錯誤信息
}
)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
