vue全家桶(Vuex,Vue Router,Vue) + axios;
在登录页面登录成功后后台返回一个 token(该 token 用于验证用户登录状态),将 token 保存在 cookies 和 store 里。之后每次在向后端发送请求时在 header 里添加一个 token 字段用于验证用户状态,如果 token 失效,接口返回状态码 300, 使用 axios 创建一个拦截器,如果返回接口的状态码为300,将清除cookies 和 store 里的 token 值并转到登录页面。
每次刷新页面后 store 里的数据会丢失, 所以将判断 cookie 里是否存在 token ,如果存在, 将其赋予到 store 中保存
创建一个 axios 拦截器
// request.js
import axios from 'axios';
import auth from './auth';
import store from './store';
import router from './router';
const request = axios.create({ //创建一个拦截器
baseURL: '',
timeout: 5000
});
request.interceptors.request.use(
config => {
if (store.state.token) {
config.headers['token'] = auth.getToken().token; // 在头部设置一个 token 字段来验证用户状态
}
return config;
},
err => {
return Promise.reject(err);
}
);
request.interceptors.response.use(
response => {
if (response.data.code === 300) {
// 如果 code 为 300 表示token已失效, 需要重新登录
store.commit('logout'); // 删除token
router.replace({ // 跳转到登录页,并记录下当前页面的路由路径
path: '/login',
query: {
redirect: router.currentRoute.path
}
});
}
return response;
},
error => {
console.log(error)
return Promise.reject(error);
}
);
export default request;
// auth.js
import Cookies from 'js-cookie';
const TokenKey = 'Admin-Token'; // 存储在cookies中的名字
export default {
getToken() {
//获取token
return Cookies.get(TokenKey);
},
setToken(token) {
//设置token
return Cookies.set(TokenKey, token);
},
removeToken() {
//删除token
return Cookies.remove(TokenKey);
}
};
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
import auth from './auth';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
user: {},
token: null,
title: ''
},
mutations: {
login: (state, data) => {
auth.setToken(data);
state.token = data;
},
logout: state => {
auth.removeToken();
state.token = null;
}
},
actions: {}
});
// main.js
//···
import auth from './auth';
import router from './router';
import store from './store';
import axios from './request';
Vue.prototype.$http = axios;
// 页面刷新时,重新赋值token
if (auth.getToken()) {
store.commit('login', auth.getToken());
}
router.beforeEach((to, from, next) => { // 给路由添加一个全局前置守卫
if (to.meta.requireAuth) { // 在路由配置中添加一个 meta.requireAuth 字段用于判断是否需要验证登录状态
if (store.state.token) {
// 通过vuex state获取当前的token是否存在
next();
} else {
next({
//如果token不存在, 跳转到登录页面, 并将当前页面的路由保存到url参数中, 以便登录成功后再跳转回当前页
path: '/login',
query: { redirect: to.fullPath }
});
}
} else {
next();
}
});
//···
// Login.vue
// 省略...
login() { //点击登录按钮后执行
this.$http
.post(
'http://127.0.0.1:8090/api',
{
account: this.from.username,
password: this.from.password
}
)
.then(e => {
if (e.data.code === '200') {
// 如果返回状态值等于200 将token存储到 cookie 中
this.$store.commit('login', {
token: e.data.data.token,
identity: e.data.data.identity
});
let redirect = decodeURIComponent(
this.$route.query.redirect || '/'
); // 获取当前页面中的redirect参数, 用于登录成功后进行跳转
this.$router.push({
path: redirect
});// 跳转到登录前的页面
} else {
// 登录失败处理
}
})
.catch(err => {
console.log(err)
});
}
// 省略...
// 省略...
logout() { // 点击退出登录按钮后
this.$store.commit('logout'); // 调用 vuex 中的logout方法用于删除 token
this.$router.replace({ // 跳转到登录页面
path: '/login'
});
}
// 省略...
至此, 一个简单的登录状态验证就搞定了