Vue項目中實現token驗證的大致思路有以下幾步:
1、第一次登陸的時候,前端調登陸接口,發送用戶名和密碼。
2、后端接受到請求之后,驗證用戶名和密碼,請求成功返回一個toke。
3、前端拿到token,將token,和當前用戶信息存入localStorage和Vuex中,並跳轉路由頁面。
4、增加路由守衛,每次跳轉路由的時候判斷localStorage或者Vuex中有沒有token,沒有就到登陸頁面,有則跳轉到對應路由。
5、每次條用后端接口,都要在請求頭中加token
6、后端判斷請求頭中偶沒有token,有拿到並驗證token,驗證成功就返回數據,驗證失敗(例如:token過期或者用戶角色權限不夠或者根本沒有傳token)就返回401。
7、如果前端拿到的狀態碼為401,就清除token信息並且跳轉到登錄頁面。
發送登錄請求(包含了第一步和第三部)
驗證的第一部就是發送一個請求,帶上你的用戶名、密碼信息
submitLogin (e) { e.preventDefault() const _this = this this.loginForm.validateFieldsAndScroll((err, values) => { if (!err) { const DATA = {...values} _this.axios.post('/api/account/login', DATA).then(function (response) { // 將返回的token和用戶信息保存到Vuex當和localStorage中 _this.$store.commit('setToken', response.token) _this.$store.commit('setAccount', response.account) // 跳轉到主頁 _this.$router.replace('/home') }) } }) },
后端驗證登錄名個密碼(第二步)
//后端驗證登錄名和密碼的規則 //1.是否缺少參數 //2.用戶是否存在 //3.密碼是否正確 //4.用戶的賬戶狀態是否正常 //2.需要驗證碼的話再考慮驗證碼是否過期 //所有驗證都沒有問題之后,返回token和該用戶信息
增加路由守衛(第四步)
實現效果,每次進行路由跳轉的時候,檢查localStorage或者Vuex里面有沒有token信息,有的話就放行,沒有就到登陸頁面。
store.commit('setToken', localStorage.getItem('token')) router.beforeEach((to, from, next) => { let dispatchAccountInfo = false //判斷要去的路由是否需要鑒權 store.commit('setNeedAuth', to.meta.auth ? true : false) //如果localStorage有token信息,但是Vuex里面沒有用戶信息 if (localStorage.getItem('token') && !store.state.account) { //就在請求一下用戶信息,保存到Vuex中 dispatchAccountInfo = store.dispatch('AccountInfo') } //如果去的路由需要鑒權並且Vue里面沒有賬戶信息, if (to.meta.auth && !store.state.account) { //localStorage里面也沒有token信息就直接當行到登陸頁面 if (!localStorage.getItem('token')) { next('/') return } //如果dispatchAccountInfo沒有值就請求一次用戶信息並保存到Vuex中 if (!dispatchAccountInfo) { dispatchAccountInfo = store.dispatch('AccountInfo') } dispatchAccountInfo.then(()=> { next() }) } next() })
請求響應攔截器(包含第5、7步)
下面的代碼是增加請求和響應的攔截器,在每一次請求后端的時候都在請求的header里面加上token信息,讓后端檢查,當前的token時候正確,有沒有過期,或者該賬戶有沒有訪問該接口的權限。
如果驗證不通過,返回401,前端接受到狀態碼如果是401就會導航到登陸頁面並清除保存的token個當前用戶的信息,若驗證通過就返回數據。
//請求攔截器,在每個請求之前給header加上token參數 axios.interceptors.request.use( config => { //如果Vuex里面已經存了token信息就取出給header加上 if (store.state.token) { config.headers.token = store.state.token } //如果localStorage里面存了token信息就取出給header加上 else if (localStorage && localStorage.getItem('token')) { config.headers.token = localStorage.getItem('token') } return config }, error => { return Promise.reject(error) }) //響應攔截器,如果響應狀態碼為401就清除token並返回登陸頁面 axios.interceptors.response.use( response => { return response.data }, error => { if (error && error.response && error.response.status) { switch (error.response.status) { //如果返回的狀態碼是401,就清楚token信息並返回到登陸頁面 case 401: store.commit('setToken', false) store.commit('setAccount', false) if (store.state.needAuth) { window.location.href = '/' } break default: return Promise.reject(error.response.data) } } else { return Promise.reject(error.response.data) } })
后端驗證token(第六步)
//1.檢查請求頭里面是否存在token信息 //2.有token信息的話是否有效 //3.該token信息代表的用戶是否有權限 //4.token信息是否過期