在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下:
1、首先新建一个api.js来全局处理接口调用
//添加一个请求拦截器
axios.interceptors.request.use(function(config) {
config.headers.token = store.state.token
return config;
}, function(error) {
alert('token不存在!')
return Promise.reject(error);
});
// 添加一个响应拦截器
axios.interceptors.response.use(function(response) {
if (response.data.Code == 10001) {
//未登录
alert(response.data.data)
localStorage.removeItem('access-user')
routerIndex.push('/login');
}else if(response.data.Code == 10002){
//token过期
alert(response.data.data)
localStorage.removeItem('access-user')
routerIndex.push('/login');
}
return response;
}, function(error) {
return Promise.reject(error);
});
let base = window.g.BASE_URL;
//通用方法
export const POST = (url, params) => {
return axios.post(`${base}${url}`, params).then(res => res.data)
}
export const GET = (url, params) => {
return axios.get(`${base}${url}`, { params: params }).then(res => res.data)
}
2、接口调用方法:
import * as API from './api.js'
export default {
//登录
login: params => {
return API.POST('/api/system/login', params).then(res => res)
//return "success";
}
}
3、路由守卫方法:
import Vue from 'vue';
import Router from 'vue-router';
import login from '@/components/login';
import home from '@/components/home';
Vue.use(Router);
const router = new Router({
routes: [
{
path: '/login',
name: 'login',
component: login
},
{
path: '/home',
name: 'home',
component: home
}
]
});
// 导航守卫
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆
router.beforeEach((to, from, next) => {
if (to.path.startsWith('/login')) {
window.localStorage.removeItem('access-user')
next()
} else {
let token = localStorage.getItem('token');
let user = JSON.parse(window.localStorage.getItem('access-user'))
if (!user && token === null || token === '') {
next({ path: '/login' })
} else {
next()
}
}
});
export default router;
4、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
<el-form ref="AccountForm" :model="account" :rules="rules" label-position="right" label-width="70px">
<el-form-item prop="userName" label="账号:">
<el-input type="text" v-model="account.userName" class="i-input-txt" maxlength="32" auto-complete="off" autofocus="true" placeholder="请输入账号手机号或邮箱"></el-input>
</el-form-item>
<el-form-item prop="password" label="密码:">
<el-input type="password" v-model="account.password" class="i-input-txt" maxlength="32" :autofocus="pwdFocus" auto-complete="off" placeholder="请输入登录密码" @keyup.enter="handleLogin"></el-input>
</el-form-item>
<el-form-item class="no-item-f">
<el-button type="primary" style="width:100%;" @click="handleLogin">登录</el-button>
</el-form-item>
</el-form>
import { mapMutations } from 'vuex';
data() {
return {
account: {
userName: '',
password: ''
},
}
},
methods: {
...mapMutations(['changeLogin']),
handleLogin(event){
let codestatus = this.checkCode();
if (codestatus) {
let params = {
userName: this.account.userName,
password: this.account.password
};
//调用函数 传递参数 获取结果
API.login(params).then(res=>{
if(res.code == '200'){
//登录成功
localStorage.setItem('access-user', JSON.stringify(res.data));
this.$cookieStore.setCookie('userName' ,res.data.account, 120);
// 将用户token保存到vuex中
this.changeLogin({token:res.token});
this.$router.push('/home');
}else{
console.log(res.code);
messageOnce.error({message: '登录失败,账号或密码错误!',type: 'error'})
return false;
}
})
}
}
}
store文件夹下的index.js:
/**
* Created by byh on 2020/5/10.
*/
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
token: null // 存储token
}
const mutations = {
// 修改token,并将token存入localStorage
changeLogin(state, user) {
state.token = user.token;
localStorage.setItem('token', user.token);
},
// 删除token
quitLogin(state) {
state.token = null
localStorage.removeItem('token');
}
}
/*从本地存储读取数据*/
for (var item in state) {
localStorage.getItem(item) ? state[item] = localStorage.getItem(item) : false;
}
export default new Vuex.Store({
state,
mutations
})
5、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token,前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面,前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面,每次调后端接口,都要在请求头中加token,后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401,如果前端拿到状态码为401,就清除token信息并跳转到登录页面!