前端React中无感刷新token

4 篇文章 0 订阅

React + umi-request 刷新token

起因:项目之前在token到期之后直接跳转到登录页,现在客户不想跳转到登录页重新登录

1、直接上代码,自定义一个request

import { refreshToken } from '@/utils/auth';
import { getCache } from '@/utils/utils';
import { history } from 'umi';
import { extend } from 'umi-request';

const loginPath = '/user/login';

const codeMessage = {
    200: '服务器成功返回请求的数据。',
    201: '新建或修改数据成功。',
    202: '一个请求已经进入后台排队(异步任务)。',
    204: '删除数据成功。',
    400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
    401: '用户没有权限(令牌、用户名、密码错误)。',
    403: '用户得到授权,但是访问是被禁止的。',
    404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
    405: '请求方法不被允许。',
    406: '请求的格式不可得。',
    410: '请求的资源被永久删除,且不会再得到的。',
    422: '当创建一个对象时,发生一个验证错误。',
    500: '服务器发生错误,请检查服务器。',
    502: '网关错误。',
    503: '服务不可用,服务器暂时过载或维护。',
    504: '网关超时。',
};

let isRefreshing = false; // 是否正在刷新token
let pendingList: any[] = []; // 等待的函数队列,用Promise实现

const customRequest = extend({
    credentials: 'include', // 默认请求是否带上cookie
});

/**
 * 请求拦截器
 */
customRequest.interceptors.request.use((url, options) =>{
    return {
        url,
        options: {
            ...options,
            headers: {
            	// 此处替换成自己的token
                Authorization: `bearer ${getCache('TOKEN')}`
            }
        }
    }
});

/**
 * 响应拦截器
 */
customRequest.interceptors.response.use(async (response, options) => {
    const { status } = response; 
    if(status === 401){
        if(!isRefreshing){
            isRefreshing = true;
            const newToken = await refreshToken(); // 获取新token
            if(newToken === ''){
                // 获取失败(RefreshToken已过期), 跳转到登录页
                pendingList = [];
                isRefreshing = false;
                history.push(loginPath);
            }else{
				pendingList.forEach(item =>item());
	            const res = await customRequest(response.url,options);
	            isRefreshing = false;
	             // 清空等待队列
	            pendingList = [];
	            return res;
			}
        }else{
            // 正在获取新token, 需要将本次请求加入到等待队列中
            return new Promise(resolve => {
				// 用函数形式将 resolve 存入,等待获取新token后再执行
                pendingList.push(() => {
					resolve(customRequest(response.url,options))
				});
			})
        }
    }
    return response;
});
export default customRequest;

refreshToken函数

/**
 * @description: 获取新token
 * @return {*}
 */
export const refreshToken = async (): Promise<string> =>{
	// 替换成自己的token和RefreshToken
    const token = getCache('TOKEN');
    const refreshToken = getCache('REFRESH_TOKEN');

    const response: ResponseResultType = await request(`替换成自己的刷新token的url`);
    if(response.Code === 200){
    	// 这里是后端自己定义的
        if(response.Msg === '未找到该刷新令牌' || response.Msg === '刷新令牌不正确'){
            return '';
        }
        const { data }: { data: RefreshTokenType} = response;
        setCache('TOKEN', data.AccessToken);
        setCache('REFRESH_TOKEN', data.RefreshToken); 
        return data.AccessToken;
    }
    return '';
}

2、后端使用的是.Net Core 6+Jwt,需要通过登录验证时生成的token和RefreshToken去获取新token

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React使用Axios的过程,如果要刷新Token重新请求接口,可以采用以下两种方式: 1.使用拦截器:Axios提供了interceptors拦截器,可以在请求或响应被处理前对它们进行全局的拦截和处理。可以在请求拦截器判断Token是否过期,如果过期,则先刷新Token,然后再重新发起请求。示例代码如下: ``` axios.interceptors.request.use( (config) => { const token = localStorage.getItem("token"); if (token) { // 判断Token是否过期,如果过期则刷新Token const decodedToken = jwt_decode(token); const currentTime = Date.now() / 1000; if (decodedToken.exp < currentTime) { // 刷新Token的代码 } config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); ``` 2.使用Promise.all():Promise.all()方法接收一个Promise对象的数组作为参数,并返回一个新的Promise对象。当所有的Promise对象都成功时,新的Promise对象才会成功;当有一个Promise对象失败时,新的Promise对象就会失败。可以在Promise.all()方法同时发起原始请求和刷新Token的请求,当Token刷新后再重新发起原始请求。示例代码如下: ``` const refreshTokenPromise = axios.post("/api/refreshToken"); const originalPromise = axios.get("/api/someApi"); Promise.all([refreshTokenPromise, originalPromise]) .then((responses) => { const originalResponse = responses[1]; // 处理原始请求的响应数据 }) .catch((error) => { // 处理错误 }); ``` 以上是两种处理方式,你可以根据实际情况选择适合自己的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值