React Native封装Fetch统一校验JWT过期时间方案咨询
封装自定义Fetch实现全局Token过期校验方案
当然可以!封装一个全局的自定义Fetch工具完全能解决你重复写Token校验逻辑的问题,还能无缝集成Redux的Action分发。我给你一套落地可行的方案:
1. 先准备Token校验工具函数
首先我们需要两个核心函数:解析JWT获取过期时间,以及判断Token是否过期。可以借助jwt-decode库来简化解析(先执行npm install jwt-decode或yarn add jwt-decode安装)。
创建utils/api.js文件,先写基础工具函数:
import jwtDecode from 'jwt-decode'; import { store } from '../store'; // 导入你的Redux Store实例 import { logoutUser, refreshToken } from '../features/auth/authSlice'; // 导入你的Auth相关Action // 解析JWT,提取过期时间等信息 const decodeJwtToken = (token) => { try { return jwtDecode(token); } catch (error) { console.error('解析JWT失败:', error); return null; } }; // 判断Token是否已过期 const isTokenExpired = (token) => { if (!token) return true; const decodedToken = decodeJwtToken(token); if (!decodedToken?.exp) return true; // 把当前时间和Token过期时间转成秒级对比 const currentTimestamp = Date.now() / 1000; return decodedToken.exp < currentTimestamp; };
2. 封装带Token校验的自定义Fetch
接下来我们把Token校验、Redux Action分发和原生Fetch整合起来,实现全局的请求拦截逻辑:
export const customFetch = async (url, options = {}) => { // 从Redux Store中获取当前的Token和刷新Token const { auth } = store.getState(); const { token, refreshToken: storedRefreshToken } = auth; // Step 1: 校验Token状态 if (isTokenExpired(token)) { try { // 有刷新Token机制的话,先尝试刷新Token const refreshRes = await fetch('/api/auth/refresh', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken: storedRefreshToken }), }); if (refreshRes.ok) { const { newToken, newRefreshToken } = await refreshRes.json(); // 分发Action更新Store里的Token store.dispatch(refreshToken({ token: newToken, refreshToken: newRefreshToken })); // 更新请求头的Authorization字段 options.headers = { ...options.headers, Authorization: `Bearer ${newToken}`, }; } else { // 刷新失败,直接分发登出Action store.dispatch(logoutUser()); throw new Error('Token已过期且刷新失败'); } } catch (refreshError) { console.error('刷新Token出错:', refreshError); store.dispatch(logoutUser()); throw refreshError; } } else { // Token有效,自动添加Authorization请求头 options.headers = { ...options.headers, Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }; } // Step 2: 发起实际的API请求 try { const response = await fetch(url, options); // 额外处理401场景(比如Token被后台拉黑) if (response.status === 401) { store.dispatch(logoutUser()); throw new Error('未授权访问'); } return response; } catch (requestError) { console.error('API请求失败:', requestError); throw requestError; } };
3. 在应用中使用自定义Fetch
现在你可以在任何需要请求API的地方,用customFetch替代原生的fetch,比如:
import { customFetch } from '../utils/api'; const fetchUserProfile = async () => { try { const res = await customFetch('/api/user/profile'); const profileData = await res.json(); // 处理用户数据 } catch (err) { // 统一处理错误(比如提示用户登录) } };
关键注意点
- 确保你的Redux Store已经配置了
redux-persist,Token会被自动持久化到本地存储(React Native中默认是AsyncStorage,不用额外处理)。 - 如果你的项目没有刷新Token的机制,可以直接删掉刷新相关的代码,Token过期后直接分发登出Action即可。
- 可以根据需求扩展这个自定义Fetch,比如添加全局的加载状态、统一的错误提示等。
内容的提问来源于stack exchange,提问作者Ali Zeynalov
相关产品推荐
相关产品推荐

