模块化封装 --- 双ToKen 实现免登录步骤详解

本文大概配置了下 双token免登录
关于下文提到的store中封装的保存token的方法,请参考本链接:

/**
 * 封装 axios 请求模块
 */
import axios from 'axios'
import jsonBig from 'json-bigint'
import store from '@/store'  
import router from '@/router' // 导入路由模块
// 配置公共请求头
const request = axios.create({
    
    
  baseURL: 'xxxxxx/', // 基础路径
  transformResponse: [ 
    // 下面的写法二“
    function(data) {
    
     // data  是后端返回的原始数据 ,一般是JSON对象,格式不确定,所以可能报错,使用try catch
      try {
    
    
        return jsonBig.parse(data) // 注意这里返回出去的 BigNumber 对象是一个对象,在使用时要注意不能直接使用,需要转换成字符串来使用
      } catch (err) {
    
    
        return {
    
    }
      }
    }
  ]
})
/**
 * 配置处理后端返回数据中超出 js 安全整数范围问题
 * 这是axios中的 api -- transformResponse , axios 默认会在内部这样处理后端返回的数据
 * 所有请求都会经过这个,写法一:
 */
// request.defaults.transformResponse = [
//   function(data) {
    
    
//     try {
    
    
//       return jsonBig.parse(data)
//     } catch (err) {
    
    
//       return {}
//     }
//   }
// ]

// 请求拦截器
request.interceptors.request.use(
  function(config) {
    
    
    const user = store.state.user
    if (user) {
    
    
      config.headers.Authorization = `Bearer ${
      
      user.token}`
    }
    // Do something before request is sent
    return config
  },
  function(error) {
    
    
    // Do something with request error
    return Promise.reject(error)
  }
)
// 响应拦截器
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')  // 直接跳转会登陆页面

        // 代码不要往后执行了
        return
      }
      // 如果有refresh_token,则请求获取新的 token
      try {
    
    
        const res = await axios({
    
    
          method: 'PUT',
          url: 'xxxxxxxxxxxx', // 设置重新获取新的token 接口
          headers: {
    
    
            Authorization: `Bearer ${
      
      user.refresh_token}` // 使用 user中存储的 refresh_token 去获取新的token
          }
        })
        // 如果获取成功,则把新的 token 更新到容器中
        console.log('刷新 token  成功', res)
        store.commit('xxx', {
    
      // 调用 store/index.js 中封装的方法来保存 新的 token  
        // 这个封装的方法在本文没有写,在该 链接中有说明 https://blog.csdn.net/weixin_47988564/article/details/108066478
        
          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')
      }
    }
    return Promise.reject(error)
  }
)
export default request

猜你喜欢

转载自blog.csdn.net/weixin_47988564/article/details/108129852
今日推荐