Vue中使用axios的响应拦截器处理请求失败的情况(处理token过期问题)以及 登录成功跳转回原来页面问题

您所在的位置:网站首页 replace跳转失败 Vue中使用axios的响应拦截器处理请求失败的情况(处理token过期问题)以及 登录成功跳转回原来页面问题

Vue中使用axios的响应拦截器处理请求失败的情况(处理token过期问题)以及 登录成功跳转回原来页面问题

2023-07-22 12:38| 来源: 网络整理| 查看: 265

参考axios官方文档

// 响应拦截器 // Add a response interceptor request.interceptors.response.use( // 在2xx范围内的任何状态代码都会触发此函数,这里主要用于处理响应数据 response => { return response }, // 任何超出2xx范围的状态码都会触发此函数,这里主要用于处理响应错误 error => { const { status } = error.response if (status === 401) { // 未授权 } else if (status === 403) { // 没有权限 } else if (status === 404) { // 资源不存在 Toast.fail({ message: '请求资源不存在', forbidClick: true }) } else if (status >= 500) { // 服务端异常 Toast.fail({ message: '服务端异常,请稍后重试', forbidClick: true }) } // 将未处理的异常往外抛 return Promise.reject(error) }) 处理 token 过期

token过期后,如果发现存在user和token则发送 刷新token的请求,请求头中携带上refresh_token的值, 请求成功后,把获取到的最新的token设置给vuex容器中的user。 因为每次请求时,请求拦截器会从vuex容器中拿token。 这样即使用户token过期了,也会自动去发送刷新token的请求来获取最新的token,而不需要用户手动去登录! 在这里插入图片描述

/* * 请求模块 * */ import axios from 'axios' // 在非组件模块中获取store 必须采用这种方式 import store from '../store/index.js' import JSONbig from 'json-bigint' import { Toast } from 'vant' import router from '../router' const request = axios.create({ baseURL: '/api', // 基础路径 transformResponse: [function (data) { // Do whatever you want to transform the data // console.log(data) // 后端返回的数据可能不是 JSON 格式字符串 // 如果不是的话,那么 JSONbig.parse 调用就会报错 // 所以我们使用 try-catch 来捕获异常,处理异常的发生 try { // 如果转换成功,则直接把结果返回 return JSONbig.parse(data) } catch (err) { console.log('转换失败', err) // 如果转换失败了,则进入这里 // 我们在这里把数据原封不动的直接返回给请求使用 return data } // axios 默认在内部使用 JSON.parse 来转换处理原始数据 // return JSON.parse(data) }] }) const refreshTokenReq = axios.create({ baseURL: '/api' // 基础路径 }) // 请求拦截器 request.interceptors.request.use(function (config) { const { user } = store.state // 如果用户已登录,统一给接口设置token if (user) { config.headers.Authorization = `Bearer ${user.token}` } // 处理完之后一定要把config 返回,否则请求发不出去 return config }, function (err) { return Promise.reject(err) }) // 响应拦截器 request.interceptors.response.use(function (response) { // 响应成功进入这里 return response }, async function (error) { // 响应失败进入这里 const status = error.response.status if (status === 400) { // 客户端请求参数错误 Toast.fail('客户端请求参数错误') } else if (status === 401) { // token无效 // 如果没有 user 或者 user.token, 直接去登录 const { user } = store.state if (!user || !user.token) { // 直接跳转到登录页面 return redirectLogin() } // 使用refresh_token,则请求获取新的token try { const { data } = await refreshTokenReq({ method: 'PUT', url: '/app/v1_0/authorizations', headers: { Authorization: `Bearer ${user.refresh_token}` } }) // 拿到新的token之后把它更新到容器中 user.token = data.data.token store.commit('setUser', user) // 把失败的请求重新发送出去 // error.config 是本次请求的相关配置项 // 注意: 这里使用request发请求,它会走自己的请求拦截器,它的请求 // 拦截器中通过store容器访问token数据 return request(error.config) // console.log(data) } catch (err) { // 刷新token都失败了,直接跳转到登录页 redirectLogin() } } else if (status === 403) { // 没有权限操作 Toast.fail('没有权限操作') } else if (status >= 500) { // 服务端异常 Toast.fail('服务端异常,请稍后重试!') } // console.dir(error) return Promise.reject(error) }) function redirectLogin () { router.replace('/login') } // 导出 export default request 登录成功跳转回原来页面

首先在响应拦截器中: 在这里插入图片描述 注意: router.currentRoute 和 我们在组件中获取的this.$route是一个东西 在这里插入图片描述 在这里插入图片描述

// 响应拦截器 request.interceptors.response.use( // 响应成功进入第1个函数 // 该函数的参数是响应对象 function (response) { // Any status code that lie within the range of 2xx cause this function to trigger // Do something with response data return response }, // 响应失败进入第2个函数,该函数的参数是错误对象 async function (error) { // Any status codes that falls outside the range of 2xx cause this function to trigger // Do something with response error // 如果响应码是 401 ,则请求获取新的 token // 响应拦截器中的 error 就是那个响应的错误对象 console.dir(error) if (error.response && error.response.status === 401) { // 校验是否有 refresh_token const user = store.state.user if (!user || !user.refresh_token) { // router.push('/login') + redirectLogin() // 代码不要往后执行了 return } // 如果有refresh_token,则请求获取新的 token try { const res = await axios({ method: 'PUT', url: 'http://ttapi.research.itcast.cn/app/v1_0/authorizations', headers: { Authorization: `Bearer ${user.refresh_token}` } }) // 如果获取成功,则把新的 token 更新到容器中 console.log('刷新 token 成功', res) store.commit('setUser', { token: res.data.data.token, // 最新获取的可用 token refresh_token: user.refresh_token // 还是原来的 refresh_token }) // 把之前失败的用户请求继续发出去 // config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有 // return 把 request 的请求结果继续返回给发请求的具体位置 return request(error.config) } catch (err) { // 如果获取失败,直接跳转 登录页 console.log('请求刷线 token 失败', err) // router.push('/login') + redirectLogin() } } return Promise.reject(error) } ) + function redirectLogin () { + // router.currentRoute 当前路由对象,和你在组件中访问的 this.$route 是同一个东西 // query 参数的数据格式就是:?key=value&key=value + router.push('/login?redirect=' + router.currentRoute.fullPath) + }

然后在登录成功以后:

const redirect = this.$route.query.redirect || "/"; this.$router.push(redirect);

在这里插入图片描述 在这里插入图片描述

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3