- 首次登录时,后端服务器判断用户账号密码正确之后,根据用户id、用户名、定义好的秘钥、过期时间生成 token ,返回给前端;
- 前端拿到后端返回的 token ,存储在 localStroage 和 Vuex 里;
- 前端每次路由跳转,判断 localStroage 有无 token ,没有则跳转到登录页,有则请求获取用户信息,改变登录状态;
- 每次请求接口,在 Axios 请求头里携带 token;
- 后端接口判断请求头有无 token,没有或者 token 过期,返回401;
- 前端得到 401 状态码,重定向到登录页面。
store.js
import Vue from 'vue' import Vuex from 'vuex' import VuexPersistence from 'vuex-persist' Vue.use(Vuex) const vuexLocal = new VuexPersistence({ storage: window.localStorage, reducer: state => ({ token: state.token, // 这个就是存入localStorage的值 WXTempKey: state.WXTempKey }) }) const store = new Vuex.Store({ state: { token: "", WXTempKey: '', isLogin: false, uid: 0, name: '', avatar: '' }, mutations: { setToken(state, token) { state.token = token }, setLogin(state, flag) { state.isLogin = flag }, setWXTempKey(state, WXTempKey) { state.WXTempKey = WXTempKey }, }, actions: {}, plugins: [vuexLocal.plugin] }) export default store
登陆页
// 登陆方法 async login() { if (!this.phone || !this.password) { // this.$toasted.error("请输入完善信息", { icon: "error" }).goAway(2000); Notify({ type: 'danger', message: "请输入完善信息", duration: 1500 }) return; } try { // await等待一个异步返回的结果 如果没有await 会报user is undefined 获取不到 let res = await this.http.post("/api/TokenAuth/MemberAuthenticate", { Phone: this.phone, PhoneCode: this.password, WXTempKey: this.$store.state.WXTempKey ? this.$store.state.WXTempKey : "" }); console.log(res); if (res.Result) { // debugger // console.log(res); // localStorage.setItem("token","res.Result.AccessToken"); this.$store.commit("setToken", res.Result.AccessToken); Toast({ mask: false, message: '登录成功', position: 'bottom' }); this.$router.replace({ name: "index" }); } else { // this.$toasted // .error(res.Error.Message, { icon: "error" }) // .goAway(2000); } } catch (error) { // this.$toasted.error(error.message, { icon: "error" }).goAway(2000); } }
http.js
import axios from 'axios' import store from './store' import { getToken } from '@/util/token' import qs from 'qs' import config from './config' import router from './router' import Vue from 'vue' import VuexPersistence from 'vuex-persist' import { Notify,Toast } from 'vant' console.log(config) // 创建axios实例 const http = axios.create({ baseURL: config.api_base, timeout: 15000, //设置请求头 headers: { // 'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type' : 'application/json', }
//利用qs解析json数据让后端可以解析
transformRequest: [
function(data, headers) {
data = data || {}
data = qs.stringify(data)
return data
}
]
}) // request拦截器 http.interceptors.request.use(config => { config.data = config.data ? config.data : {} config.headers["authorization"] =store.state.token; //把token添加到请求头每次请求接口时候带上
if(config.method=='get'){ Toast({ mask: false, message: '加载中...', position: 'bottom' }); }else{ Toast.loading({ mask: true, message: '加载中...', position: 'middle', loadingType:'spinner' }); } if (router.currentRoute && router.currentRoute.meta.requiresAuth) { if (localStorage.getItem('user')) { return Promise.reject('请登录后操作') } else { // config.headers.Authorization = token; // config.headers['authorization'] = `${store.state.token}`; console.log('interceptors config=',config) return config } } else { return config } }) // respone拦截器 http.interceptors.response.use( response => { let data = response.data let msg = data.message || '' Toast.clear(); if (response.status === 200) { if (response.data.Result) { if (response.data.Result.Code && response.data.Result.Code !== 0) { Notify({ type: 'danger', message: response.data.Result.Message, duration: 1500 }) return Promise.resolve(response.data) } else { return Promise.resolve(response.data) } }else { return Promise.resolve(response.data) } } else { Notify({ type: 'danger', message: '请求失败,请稍后再试!!!', duration: 1500 }) return Promise.reject(response) } // if (data.code == 401) { // // 账号禁用 // Vue.toasted.error(data.message, { icon: 'error' }).goAway(2000) // router.replace({ name: 'login' }) // return Promise.reject(new Error(msg)) // } else if (data.code == 403) { // // 登录失效 需重新登录 // Vue.toasted.error('登录失效 需重新登录', { icon: 'error' }).goAway(2000) // router.replace({ name: 'login' }) // return Promise.reject(new Error(msg)) // } else if (data.code == 400) { // return Promise.reject(new Error(msg)) // } // return data }, err => { Toast.clear(); if (err.response.data.Error) { Notify({ type: 'danger', message: err.response.data.Error.Message, duration: 1500 }) if(err.response.status == 401 || (err.response.data.Error && err.response.data.Error.Code)){ console.log(router) store.commit("setToken", ''); router.push({ path: "/login", query:{ redirect:router.currentRoute.fullPath } }); } } else { Notify({ type: 'danger', message: '请求失败!!!', duration: 1500 }) } return Promise.reject(err) } ) export default http