token失效问题的解决方案

import axios from 'axios';
import type {
    AxiosRequestConfig,
    AxiosResponse,
} from 'axios';


import {
    setToken,
    getToken,
    loginOut,
} from '@/core/auth';
import {
    updataTokenAPI
} from '@/api/admin/auth'
import {
    ElLoading,
} from 'element-plus'

import { ElMessage } from 'element-plus'




axios.defaults.timeout = 100000;
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.headers.post['Content-Type'] = 'application/json';
axios.defaults.headers.get['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_URL;


const instance = axios.create();

interface YXRequestConfig extends AxiosRequestConfig {
    headers?: any
}

export interface RequestConfig {
    timeout?: number;//延长时间

    then?: boolean;//是否错误了自行处理 不统一报错

    hideLoading?: boolean,//是否显示loading

    request?: AxiosRequestConfig,//axiox的配置
}



let timer: number;
let loadingInstance1: ReturnType<typeof ElLoading.service> | undefined;
function showLoading() {
    clearTimeout(timer);
    if (loadingInstance1) return;
    loadingInstance1 = ElLoading.service({
        fullscreen: true,
        lock: true,
        text: '加载中...',
        background: 'rgba(0,0,0,.6)',
    })
}
function hideLoading() {
    clearTimeout(timer);
    if (loadingInstance1) {
        timer = window.setTimeout(() => {
            loadingInstance1?.close();
            loadingInstance1 = undefined;
        }, 200)
    }
}
/**
 * TODO 客户端请求拦截
 */
instance.interceptors.request.use(function (config) {
    let token = getToken();
    if (token) {
        config.headers['Authorization'] = token;
    }
    return config;
})

/**
 * 服务端返回拦截
 */
instance.interceptors.response.use(function (response: AxiosResponse) {
    hideLoading();
    if (response.headers.Authorization) {
        setToken(response.headers.Authorization)
    }
    // 对响应数据做点什么
    return response;
}, async (error) => {
    hideLoading();
    if (error.response && error.response.status === 401) {
        let username = localStorage.getItem('loginUserName')
        //请求刷新token接口
        const { data: res } = await updataTokenAPI({
            username
        })
        //保存新的token值
        setToken(res);
        // 再调用一次未完成的请求啊(用户无感知)
        // error.config 就是上一次axios请求的配置对象
        // 把新的token赋予到下一次axios请求的请求头中 
        error.config.headers.Authorization = res
        // return到await的地方,将未完成的请求再次发起,
        return axios(error.config)
    } else if (error.response.status === 500 && error.config.url === '/auth/user/refresh_token') {
        // 因为500的情况有很多种,refresh_token失效也是其中一种情况,所有再加上error.config.url === '/v1_0/authorizations'条件,确保是refresh_token失效情况
        // 清空所有的token和refresh_toekn,并且强制跳转登录页面
        ElMessage.error('身份已过期!');
        loginOut();
    }
    return error
})


let REFRESH_COUNT = 0;

async function toRequest<T = any>(params: AxiosRequestConfig, config: RequestConfig = {}): Promise<ResponseResult<T>> {
    if (!config.hideLoading) {
        showLoading();
    }

    let request = config.request || {};
    try {
        let result = await instance({
            ...params,
            ...request,
            timeout: config.timeout,
        });
        let data: ResponseResult<T> = result.data;
        // console.log('data--2')
        // console.log(data)
        if (!(data instanceof Blob)) {
            if (data.code === 40002) {
                loginOut();
            }
            //去登录
            if (data.code === 10000) {
                return Promise.reject();
            }
            if (data.code !== SUCCESSCODE && !config.then) {
                ElMessage.error(data.message);
                return Promise.reject(data);
            }
        }
        return data;
    } catch (e) {
        return Promise.reject(e);
    }
}

export function get<T = any>(url: string, data: object = {}, config?: RequestConfig): Promise<ResponseResult<T>> {
    return toRequest(
        {
            url,
            method: 'get',
            params: data,
        },
        config,
    )
}
export function post<T = any>(url: string, data: object = {}, config?: RequestConfig): Promise<ResponseResult<T>> {
    return toRequest<T>(
        {
            url,
            method: 'post',
            data: data,
        },
        config,
    )
}

export function downxlsx<T = any>(url: string, data: object = {}, config?: RequestConfig): Promise<ResponseResult<T>> {
    return toRequest<T>(
        {
            url,
            method: 'post',
            data: data,
        },
        config,
    )
}

export function upload<T = any>(url: string, data: any, config?: RequestConfig): Promise<ResponseResult<T>> {
    return toRequest<T>(
        {
            url,
            method: 'post',
            data: data,
            headers: {
                'Content-Type': 'multipart/form-data',
            },
        },
        config,
    )
}



export const blobParams = {
    request: {
        responseType: 'blob',
    }
} as const;

你可能感兴趣的:(前端,javascript,java)