vuex登錄驗證及保持登錄狀態
不知道vuex的可以先看一下 vuex官方文檔,這里就不贅述了。
實現思路:假設我們現在想要訪問自己在博客園里寫的博客,這時候服務器需要知道當前用戶是誰,才能確定我們是否有訪問權限並正確地返回我們需要的信息,因此這里必須要進行用戶名密碼驗證,即登錄操作,驗證成功則跳轉到請求頁面,不成功則跳轉到登錄頁。關於驗證這里有兩種情況,一種是輸入用戶名和密碼以后點擊登錄會觸發驗證,第二種是沒有點擊登錄,只是單純的路由跳轉,這時候可能存在用戶名密碼過期從而驗證失敗的情況,所以我們的驗證也要在點擊登錄以及頁面跳轉這兩種情況下進行。
首先寫一個登錄框,為登錄按鈕添加login事件
<el-form ref="loginForm" :model="loginForm" label-width="70px" > <el-form-item label="用戶名" prop="username"> <el-input v-model="loginForm.username" placeholder="請輸入用戶名"></el-input> </el-form-item> <el-form-item label="密碼" prop="password"> <el-input type="password" v-model="loginForm.password" @keyup.enter.native="login" placeholder="請輸入密碼"></el-input> </el-form-item> <el-form-item> <el-button type="primary" class="button" @click="login">登錄</el-button> </el-form-item> </el-form>
點擊登錄按鈕后觸發store的action里的Login方法,並將用戶名和密碼作為參數傳遞過去
login () {
let params = { 'username': this.loginForm.username, 'password': this.loginForm.password }; this.$store.dispatch('Login', params) .then(() => {this.$router.push({ path: '/' }); }) .catch((error) => { console.log(error.response); }); }
退出登錄時觸發action里的LogOut方法
logOut () { this.$store.dispatch('LogOut').then(() => { //跳轉到登錄頁面 this.$router.push('/login'); }) }
創建store.js文件
import Vue from 'vue'; import Vuex from 'vuex'; import axios from 'axios'; const store = new Vuex.Store({ state: { status: '', token: localStorage.getItem('token') || '', user: {} }, mutations: { auth_request(state) { state.status = 'loading'; }, auth_success(state, token, user) { state.status = 'success'; state.token = token; state.user = user; }, auth_error(state) { state.status = 'error'; }, logout(state) { state.status = ''; state.token = ''; }, }, actions: { Login({commit}, user) { return new Promise((resolve, reject) => { commit('auth_request')
// 向后端發送請求,驗證用戶名密碼是否正確,請求成功接收后端返回的token值,利用commit修改store的state屬性,並將token存放在localStorage中 axios.post('login', user) .then(resp => { const token = resp.data.token const user = resp.data.user localStorage.setItem('token', token)
// 每次請求接口時,需要在headers添加對應的Token驗證 axios.defaults.headers.common['Authorization'] = token // 更新token commit('auth_success', token, user) resolve(resp) }) .catch(err => { commit('auth_error') localStorage.removeItem('token') reject(err) }) }) }, LogOut({ commit, state }) { return new Promise((resolve, reject) => { axios.get('Logout') .then(response => { removeIsLogin() localStorage.removeItem('loginUsername');
// 移除之前在axios
頭部設置的token,現在將無法執行需要token的事務
delete axios.defaults.headers.common['Authorization'];
resolve(response) }) .catch(error => { reject(error) }) }) } }, getters: {
// !!將state.token強制轉換為布爾值,若state.token存在且不為空(已登錄)則返回true,反之返回false
isLoggedIn: state => !!state.token,
authStatus: state => state.status
} }); export default store;
用router.beforeEach控制路由跳轉時訪問頁面的權限 (關於to.matched.some的解釋見 https://router.vuejs.org/zh/guide/advanced/meta.html)
router.beforeEach((to, from, next) => { // 檢測路由配置中是否有requiresAuth這個meta屬性 if (to.matched.some(record => record.meta.requiresAuth)) { // 判斷是否已登錄 if (store.getters.isLoggedIn) { next(); return; } // 未登錄則跳轉到登錄界面 next('/login'); } else { next() } })
攔截axios請求處理token過期問題
axios.interceptors.response.use( response => { return response; }, error => { if (error.response) { switch (error.response.status) { case 401: //跳轉登錄 this.$store.dispatch(logout); } } } );