双token时前端access_token的换取

该博客详细介绍了如何在Vue项目中使用axios库进行API请求,包括设置基础URL、超时处理、全局loading、错误处理以及针对401未授权情况下的token刷新机制。在遇到401错误时,通过刷新token实现会话延续,并在刷新成功后重新发送被拦截的请求。
摘要由CSDN通过智能技术生成
import axios from 'axios';
import qs from 'qs';
import router, {
  resetRouter
} from '../router';
import {
  Loading,
  Message
} from 'element-ui';
import * as local from '@/utils/localStorage.js';

// 接口请求个数
let requestCount = 0;
// 是否正在刷新token
let isRefreshing = false;
// 重新请求的接口
let requests = [];
let loading;

function showFullScreenLoading () {
  if (requestCount === 0) {
    loading = Loading.service({
      lock: true,
      text: '加载中……',
      background: 'rgba(0, 0, 0, 0.7)'
    });
  }
  requestCount++;
}

function tryHideFullScreenLoading () {
  if (requestCount <= 0) return;
  requestCount--;
  if (requestCount === 0) {
    loading.close();
  }
}

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 10000
});

// 换取新的token值
export function refreshToken (data) {
  return service({
    //填写换取新access_token的地址
    url: 'oauth/token',
    //method,data,auth等参数的值根据自己接口来定
    method: 'post',
    data: qs.stringify(data),
    auth: {
      username: '',
      password: ''
    }
  });
}

service.interceptors.request.use(function (config) {
  // 在发送请求之前获取token是否存在
  var token = local.getToken();
  if (token) {
    config.headers.Authorization = 'Bearer ' + token;
  }
  //显示loading
  showFullScreenLoading();
  return config;
}, function (error) {
  // 抛出错误
  return Promise.reject(error);
});

service.interceptors.response.use(function (response) {
  //关闭loading
  tryHideFullScreenLoading();
  return response;
}, function (error) {
  if (error.message.includes('timeout')) {
    if (!window.timeoutTip) {
      Message.error('连接超时');
      window.timeoutTip = 1;
    }
  }
  if (error && error.response) {
    //判断当前是否换取token的接口
    if (error.response.status === 401 && error.response.config.url.indexOf('oauth/token') < 0) {
      const config = error.response.config;
      if (!isRefreshing) {
        isRefreshing = true;
        const refreshData = {
          grant_type: 'refresh_token',
          refresh_token: local.getRefreshToken()
        };
        return refreshToken(refreshData).then(res => {
          if (res.status === 200) {
            local.setToken(res.data.access_token);
            local.setRefreshToken(res.data.refresh_token);
            // 重置配置
            config.headers.Authorization = 'Bearer ' + res.data.access_token;
            requests.forEach(cb => cb(res.data.access_token));
            requests = [];
            isRefreshing = false;
            tryHideFullScreenLoading();
            return service(config);
          }
        }).catch(() => {
          Message.error('您的登录已经超时或者在另一个设备登录,您被迫下线');
          local.clearLocalStorage();
          //因为项目有账号权限,需要重置路由
          resetRouter();
          router.push({
            path: '/login'
          });
          isRefreshing = false;
          tryHideFullScreenLoading();
        });
      } else {
        return new Promise((resolve) => {
          // 将resolve放进队列,用函数保存,token刷新后执行
          requests.push((token) => {
            config.headers.Authorization = 'Bearer ' + token;
            resolve(service(config));
          });
          tryHideFullScreenLoading();
        });
      }
    }
  }
  tryHideFullScreenLoading();
  return Promise.reject(error);
});

export default service;

文章仅供参考,欢迎各位大神提意见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值