React中如何校验JWT有效性以正确实现refreshToken机制
React 搭配 JWT + Refresh Token 鉴权的全局校验方案
首先直接给结论:不需要在每个页面单独发起API做JWT校验,所有校验、刷新逻辑全局统一处理即可,覆盖页面重载、组件重渲染、接口请求的全场景,具体实现分3个核心环节:
1. 先修正现有代码的基础问题
你贴的登录函数有两个容易踩坑的问题,先改掉:
- 拼写错误:请求头字段
Autorization少了个h,正确写法是Authorization,拼错会导致后端拿不到token,直接返回401 - 不必要的
async/await和.then混用,逻辑冗余
修正后的代码如下:
// Login user const login = async (userData) => { const response = await axios.post('/authentication_token', userData) const data = response.data localStorage.setItem('user', JSON.stringify(data)) axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}` return data }
2. 页面重载时的初始化校验
在React应用的根入口(一般是App.jsx或者main.jsx)的挂载生命周期里(函数组件用useEffect依赖空数组)做一次全局初始化即可,不需要每个页面重复做:
- 第一步:从localStorage读取之前存储的token和refresh_token,没有存的话直接判定未登录,跳登录页
- 第二步:本地前置校验JWT有效性,不用发请求——JWT的第二段payload是base64编码的,可以直接本地解析拿到
exp(过期时间戳),和当前时间对比:- 如果token已经过期/即将过期(你测试5秒有效期的话,可以设成剩余2秒就触发刷新),直接调用refresh token接口换新token
- 刷新成功就更新localStorage里的用户信息,同时把新token塞到axios默认请求头
- 刷新失败(refresh token过期、无效)就清空localStorage,跳登录页
- 如果token还在有效期,直接把token塞到axios默认请求头即可
本地解析JWT不用额外引第三方库,写个简单工具函数就行:
const parseJwt = (token) => { try { return JSON.parse(atob(token.split('.')[1])) } catch (err) { return null } }
注意:本地解析exp只是前置优化,用来减少不必要的refresh请求,不能作为最终有效性判断依据——毕竟本地时间可能被篡改,token也可能被后端加入黑名单,最终有效性以后端返回为准。
3. 组件重渲染、接口请求时的自动校验
直接用axios的全局拦截器统一处理,所有组件发请求的时候自动走校验逻辑,完全不用在业务页面写重复代码:
- 请求拦截器:每次发请求前,先从localStorage拿最新的token,解析exp判断是否临近过期,如果临近过期就先暂停当前请求,调用refresh接口拿新token,更新本地存储和请求头之后,再用新token继续发之前暂停的请求;没过期就正常带上请求头发送。
- 响应拦截器:如果接口返回401状态码(比如本地时间不准判断失误、token刚好在请求过程中过期),自动触发refresh token逻辑:
- 刷新成功就重新发送刚才返回401的请求
- 刷新失败就清空本地登录状态,跳转到登录页
这里要加个简单的防抖锁:多个请求同时触发401的时候,只发第一个refresh请求,剩下的请求等第一个refresh请求返回结果后再统一处理,避免重复打refresh接口。
这套逻辑跑通之后,不管是页面重载、组件重渲染还是用户操作触发接口请求,都会自动完成token校验和刷新,不需要每个页面单独写校验逻辑。你现在把token设成5秒有效期测试的话,只要正常操作触发接口,就能看到自动刷新的效果。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

