每个请求都需要携带 token ,所以我们可以使用 axios request 拦截器,在这里,我们给每个请求都加 token,这样就可以节省每个请求再一次次的复制粘贴代码。
token 失效问题,当我们token 失效,我们服务端会返回一个特定的错误表示,比如 token invalid,但是我们不能在每个请求之后去做刷新 token 的操作呀,所以这里我们就用 axios response 拦截器,我们统一处理所有请求成功之后响应过来的数据,然后对特殊数据进行处理,其他的正常分发。
// 给axios添加一个请求拦截器,axios.interceptors.request.use(config =>{// 为请求头添加一个Authorization属性,值为token// 这样后,当你请求别的接口时服务器就会先判断你的请求头中有没有Authorization这个属性,// 如果没有,就会驳回你的请求.config.headers.Authorization = window.sessionStorage.getItem('token');// 在最后必须return一个cofigreturn config})
axios二次封装
import axios from 'axios'import { MessageBox, Message } from 'element-ui'import storage from './storage'import config from '@/config/index'import router from '@/router/index'// 创建axios对象,并设置请求信息,用于设置请求拦截器const service = axios.create({// 配置请求基础地址baseURL: config.baseApi,// 设置请求超时时间timeout: 5000})// 请求拦截service.interceptors.request.use(res => {// 在每一次请求时携带上tokenconst Token = storage.getItem('Token')if (Token) {res.headers.Token = Token}return res},error => {// do something with request errorconsole.log(error) // for debugreturn Promise.reject(error)})service.interceptors.response.use(res => {const { code, data, message } = res.data// token未过期时,返回的数据if (code === 200) {return data} else {// token过期时返回的数据if (code === 401) {MessageBox.alert('登录已过期,请重新登录!')router.push({ path: '/' })} else if (code === 403) {MessageBox.alert('您没有访问权限')} else if (code === 404) {MessageBox.alert('访问失败,请检查网络')} else if (code === undefined) {return res.data} else {MessageBox.alert(message, '警告', {confirmButtonClass: 'el-button--myPrimary',type: 'warning'})}return Promise.reject(new Error('error'))}},error => {Message({message: error.message,type: 'error',duration: 5 * 1000})return Promise.reject(error)})// 封装request请求function request (options) {// 设置默认数据options.method = options.method || 'get'options.baseURL = options.baseURL || ''if (options.method.toLowerCase() === 'get') {options.params = options.data}// if (config.env === 'prod') {// service.defaults.baseURL = config.baseApi// } else {// service.defaults.baseURL = config.mock ? config.mockApi : config.baseApi// }// 设置基础路径地址,根据不同的接口设置不同的基础路径service.defaults.baseURL = options.baseURL// 将数据传递给axios对象,并返回return service(options)}// 给request对象创建不同类型的函数,这样使用时就可以通过request.get(url, data, options){}的方式使用['get', 'post', 'put', 'delete', 'patch'].forEach(item => {request[item] = (url, data, options) => {//返回一个请求接口对象return request({url,data,method: item,...options})}})// 导出axios对象,二次封装后的对象export default request
自动刷新token
Vue.use(Vuex)Vue.use(VueAxios, axios)Vue.use(qs)注:qs,。在 request 拦截器实现axios.interceptors.request.use(config => {config.baseURL = '/api/'config.withCredentials = true // 允许携带token ,这个是解决跨域产生的相关问题config.timeout = 6000let token = sessionStorage.getItem('access_token')let csrf = store.getters.csrfif (token) {config.headers = {'access-token': token,'Content-Type': 'application/x-www-form-urlencoded'}}if (config.url === 'refresh') {config.headers = {'refresh-token': sessionStorage.getItem('refresh_token'),'Content-Type': 'application/x-www-form-urlencoded'}}return config},error => {return Promise.reject(error)})//在 response 拦截器实现axios.interceptors.response.use(response => {// 定时刷新access-tokenif (!response.data.value && response.data.data.message === 'token invalid') {// 刷新tokenstore.dispatch('refresh').then(response => {sessionStorage.setItem('access_token', response.data)}).catch(error => {throw new Error('token刷新' + error)})}return response},error => {return Promise.reject(error)})
