每次请求时,检查 JWT Token的有效期并决定是否需要刷新

为了在每次请求时检查 access_token 的有效期,并在过期时自动刷新,可以通过以下步骤实现:

1. 解析 JWT Token 获取过期时间

JWT token 的有效期是编码在 token 本身的,你可以通过解析 token 来获取它的到期时间。JWT token 是由三个部分组成的:headerpayloadsignature,有效期信息通常在 payload 中。

JWT 的 payload 中有一个 exp 字段,它表示 token 的过期时间(单位为 Unix 时间戳)。前端可以通过解析这个字段来判断 token 是否已经过期。

示例:解析 JWT token 获取过期时间
javascript 复制代码
// 解析 JWT token
function parseJwt(token) {
    try {
        const base64Url = token.split('.')[1];
        const base64 = decodeURIComponent(atob(base64Url).split('').map(function(c) {
            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
        }).join(''));
        return JSON.parse(base64);
    } catch (error) {
        console.error('Invalid token:', error);
        return null;
    }
}

通过 parseJwt 方法,可以从 access_token 中提取 exp 字段(过期时间)。

2. 检查 token 是否过期

在每次发出请求前,检查当前的 access_token 是否即将过期。如果过期,使用 refresh_token 请求新的 access_token,然后继续发送请求。

检查 token 有效期并自动刷新
javascript 复制代码
// 获取当前时间的 Unix 时间戳
function getCurrentTimestamp() {
    return Math.floor(Date.now() / 1000);
}

// 检查 access_token 是否过期
function isTokenExpired(token) {
    const tokenData = parseJwt(token);
    if (!tokenData || !tokenData.exp) {
        return true;  // token 无效或没有过期字段,视为过期
    }
    const currentTime = getCurrentTimestamp();
    return tokenData.exp < currentTime;
}

// 刷新 token 的函数
async function refreshToken() {
    const refresh_token = localStorage.getItem('refresh_token');
    const response = await fetch('http://localhost:8000/api/token/refresh/', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            refresh: refresh_token,
        }),
    });

    const data = await response.json();
    if (response.ok) {
        // 更新 access_token
        localStorage.setItem('access_token', data.access);
        console.log('Token refreshed');
        return data.access;
    } else {
        console.error('Failed to refresh token:', data);
        return null;  // 失败时返回 null
    }
}

3. 统一的请求封装

为了让每次请求都经过 token 的有效性检查,可以创建一个封装的请求方法。这个方法在请求前先检查 access_token 是否过期,过期则调用 refreshToken() 获取新的 access_token,然后重新发起请求。

统一的请求方法
javascript 复制代码
async function apiRequest(url, options = {}) {
    let token = localStorage.getItem('access_token');
    
    // 检查 token 是否过期
    if (isTokenExpired(token)) {
        console.log('Access token expired, refreshing token...');
        token = await refreshToken();
        if (!token) {
            console.error('Unable to refresh token, please login again.');
            // 可以根据需求引导用户重新登录
            return null;
        }
    }

    // 设置请求头,携带最新的 access_token
    options.headers = {
        ...options.headers,
        'Authorization': `Bearer ${token}`,
    };

    // 发送请求
    const response = await fetch(url, options);
    
    // 处理响应
    if (response.ok) {
        return await response.json();
    } else {
        console.error('Request failed:', response);
        return null;
    }
}

4. 使用统一的请求方法

在实际使用中,每次发起 API 请求时,使用封装好的 apiRequest 方法:

javascript 复制代码
// 获取受保护的资源
async function getProtectedData() {
    const data = await apiRequest('http://localhost:8000/api/protected/', {
        method: 'GET',
    });
    
    if (data) {
        console.log('Protected data:', data);
    } else {
        console.error('Failed to fetch protected data');
    }
}

5. 自动刷新 token 的策略

通常情况下,刷新 access_token 的时间可以比它实际过期的时间稍微提前一些,以避免在 token 完全过期后导致请求失败。你可以在检查 token 时,判断它是否接近过期(比如还有5分钟过期),提前刷新 token:

javascript 复制代码
// 设置提前刷新时间,比如提前5分钟
const REFRESH_THRESHOLD = 300;  // 300 秒 = 5 分钟

function isTokenAboutToExpire(token) {
    const tokenData = parseJwt(token);
    if (!tokenData || !tokenData.exp) {
        return true;  // 如果没有有效的 exp 字段,视为即将过期
    }
    const currentTime = getCurrentTimestamp();
    return (tokenData.exp - currentTime) < REFRESH_THRESHOLD;
}

总结

  1. 解析 JWT Token :通过解析 token 的 exp 字段获取过期时间。
  2. 检查 token 有效期:在每次请求之前检查 token 是否过期或即将过期。
  3. 刷新 token :如果 token 过期或即将过期,使用 refresh_token 获取新的 access_token
  4. 统一封装请求方法:通过封装一个请求函数,在每次请求时都先检查和刷新 token。
  5. 提前刷新策略:可以设置在 token 过期前的几分钟内就自动刷新,确保用户体验顺畅。

通过这种方式,前端可以在每次请求时确保使用的是最新的 access_token,并自动处理 token 的过期和刷新。

相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪3 小时前
CSS复习
前端·css
咖啡の猫5 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5818 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路8 小时前
GeoTools 读取影像元数据
前端
ssshooter9 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal10 小时前
关于RSA和AES加密
前端·vue.js
柳杉10 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化