關鍵詞:前後端分離、jwt、登錄、權限驗證
最近在做一個小應用,需要用到vue實現登錄,以及給不同路由設置權限。在網上看了很多文章,講的是亂七八糟。感嘆國內技術類文章實在是差勁,抄來抄去。這篇文章就說說我最後是如何實現的。
前後端分離項目中,後端提供api接口給前端,使用jwt發放權限。
首先前端提供用戶名和密碼請求登錄接口,後端驗證之後返回給前端一個token,之後前端在請求需要權限的接口時攜帶這個token就可以了。
兩個問題
現在面臨兩個問題,
首先vue中不同的路由有不同的權限,比如我要訪問後臺 /admin, 就需要先登錄才行,而有的頁面不需要登錄。
第二個問題是,vue組件中使用axios請求後臺服務時,不同的接口有不同的權限。
後端接口權限
先來解決第二個問題。vue不同組件都要用到axios,我們在全局爲axios添加request和response的攔截器。
也就是,在發起請求之前,先檢測header是否攜帶token信息。在接收響應之前,先查看後端返回狀態碼,如果說需要token驗證就跳轉到登錄界面。
在main.js添加如下,或者新增一個http.js文件:
// * http request 攔截器
axios.interceptors.request.use(
config => {
// * 判斷是否存在token,如果存在的話,則每個http header都加上token
// * token會在登錄之後存儲在本地
if (localStorage.token) {
config.headers["Authorization"] = `Bearer ${localStorage.token}`;
}
return config;
},
err => {
return Promise.reject(err);
});
// * http response 攔截器
axios.interceptors.response.use(
response => {
let data = response.data;
// * 正常返回數據
if (data.code === 0) {
// * 返回data
return data
}
// * 如果code是20103 表示token未認證(後端定義的錯誤碼)
// * 跳轉到login
if (data.code === 20103) {
router.replace('/login')
}
return Promise.reject(data);
},
error => {
return Promise.reject(error);
});
Vue.prototype.$http = axios;
現在發起的任何請求之前都會檢查是否攜帶token,如果沒有就跳到login界面。
在login中,攜帶用戶名和密碼獲取token之後,存放到本地。
login.vue:
axios.post('/api/login', {
email: this.email,
password: this.password
}) .then((res) => {
// * 存儲token
localStorage.setItem('token', res.data.token);
console.info("login successful");
// * 跳轉回登錄前頁面
this.$router.push({path: this.$route.query.redirect || '/admin',})
}).catch((error) => {
console.error(error)
});
前端vue路由權限
現在,訪問後端接口的權限問題解決了。但是在vue中我不同的頁面有不同的訪問權限該如何處理?vue-router官方文檔給出了例子:
在需要權限的路由添加meta信息,表明該路由需要登錄才能訪問,然後在所有路由跳轉之前添加處理函數,如果沒有auth,跳轉到登錄:
path: '/admin',
name: 'admin',
component: () => import('../views/admin/Admin.vue'),
// * 需要登錄才能訪問
meta: {requiresAuth: true},
// * 全局鉤子
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// * 對於需要auth的路徑
// * 沒有token信息,redirect to login
if (!localStorage.token) {
next({
path: '/login',
query: {redirect: to.fullPath}
})
} else {
next()
}
} else {
next() // 確保一定要調用 next()
}
})
登出的話,清除token信息即可。
localStorage.removeItem("token")
以上,希望有幫助。