每次请求时,检查 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 的过期和刷新。

相关推荐
转转技术团队11 分钟前
多代理混战?用 PAC(Proxy Auto-Config) 优雅切换代理场景
前端·后端·面试
南囝coding12 分钟前
这几个 Vibe Coding 经验,真的建议学!
前端·后端
gnip26 分钟前
SSE技术介绍
前端·javascript
yinke小琪41 分钟前
JavaScript DOM节点操作(增删改)常用方法
前端·javascript
枣把儿1 小时前
Vercel 收购 NuxtLabs!Nuxt UI Pro 即将免费!
前端·vue.js·nuxt.js
望获linux1 小时前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
爱编程的喵1 小时前
从XMLHttpRequest到Fetch:前端异步请求的演进之路
前端·javascript
喜欢吃豆1 小时前
深入企业内部的MCP知识(三):FastMCP工具转换(Tool Transformation)全解析:从适配到增强的工具进化指南
java·前端·人工智能·大模型·github·mcp
豆苗学前端1 小时前
手把手实现支持百万级数据量、高可用和可扩展性的穿梭框组件
前端·javascript·面试
不见_1 小时前
不想再写周报了?来看看这个吧!
前端·命令行