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); } } } );