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信息是否过期