React Redux项目JWT过期自动登出实现与相关问题咨询
JWT过期自动登出、Redux中间件封装及npm漏洞问题解决方案
一、JWT过期自动登出兼容socket.io的实现方案
此前401状态码触发登出逻辑报错的常见诱因是并发请求同时返回401,导致登出逻辑多次重复执行,触发状态更新冲突;另外socket.io长连接场景下的鉴权失败不会走HTTP请求的响应拦截,也会出现过期未登出的情况,可通过三层逻辑兜底实现稳定触发:
- 给HTTP响应拦截器的401处理逻辑加防抖,设置300ms的延迟,同一时间多个401响应只会触发一次登出操作,避免重复执行清token、跳转登录页的逻辑
- 新增socket.io事件监听:监听socket自带的
error事件,以及后端自定义的token_expired推送事件,收到事件后直接触发登出逻辑,覆盖长连接场景的鉴权失败情况 - 增加token前置校验:JWT的payload中自带
exp过期时间戳字段,每次发起请求/触发用户操作前先解码token校验过期时间,提前30秒预判过期就主动触发登出,不用等待401响应返回,减少报错概率
二、token校验逻辑封装到Redux applyMiddleware的实现
Redux中间件的结构为store => next => action => {},可以在所有action被reducer处理前统一执行token校验逻辑,实现代码如下:
// JWT解码工具函数,也可直接引入jwt-decode库实现 const decodeToken = (token) => { if (!token) return null try { return JSON.parse(atob(token.split('.')[1])) } catch (err) { return null } } // 自定义鉴权中间件 const authMiddleware = store => next => action => { const { auth: { token } } = store.getState() // 存在token时先校验是否过期 if (token) { const decodedToken = decodeToken(token) // JWT的exp字段为秒级时间戳,需转换为毫秒和当前时间对比 if (decodedToken && decodedToken.exp * 1000 < Date.now()) { // 触发登出action清空用户状态 store.dispatch({ type: 'AUTH_LOGOUT' }) // 跳转登录页,可根据项目路由实现调整 window.location.replace('/login') // 阻断后续action执行 return } } // 校验通过则继续执行后续流程 return next(action) } // 注册中间件到Redux store import { createStore, applyMiddleware } from 'redux' import thunk from 'redux-thunk' import rootReducer from './reducers' const store = createStore( rootReducer, applyMiddleware(thunk, authMiddleware) )
该中间件和现有HTTP拦截器逻辑不冲突,中间件做前置拦截,拦截器做兜底校验,同时加防抖即可避免重复触发登出。
三、npm audit 漏洞提示原因及解决方案
你使用的Node.js v14.18.0为2021年发布的旧版本,目前已经停止官方维护,对应npm版本及适配该版本的依赖包普遍存在已知安全漏洞,常见诱因和解决方法如下:
- 常见诱因:如果项目是通过Create React App创建,旧版本
react-scripts自带大量开发依赖漏洞,这类漏洞仅影响本地开发环境,不会打包到生产代码中;另外项目中用到的redux、socket.io等依赖的旧版本也存在公开的安全漏洞,会被audit扫描到。 - 解决方案:
- 执行
npm audit --production仅扫描生产依赖的漏洞,如果生产依赖无风险可忽略开发依赖的漏洞提示 - 可执行
npm audit fix自动修复兼容范围内的漏洞,无法自动修复的可手动升级对应依赖到无漏洞的版本 - 若要彻底解决,建议将Node.js升级到当前处于维护期的LTS版本(v18/v20),再重新安装所有依赖
- 执行
内容的提问来源于stack exchange,提问作者user15368351
相关产品推荐
相关产品推荐

