React中JWT token过期如何实现自动登出?代码应写在哪个页面?
自动登出逻辑放置位置
自动登出逻辑最优放置位置为你已经在用的ProtectedRoutes路由守卫组件,原因如下:
- 所有需要登录权限的页面都会经过该组件,逻辑仅需编写一次即可全局生效
- 可以在路由跳转阶段就完成token有效性校验,无需等待页面加载后再处理,体验更优
如果项目封装了全局请求工具(如axios),可以同时在请求/响应拦截器中补充自动登出逻辑,处理接口调用过程中token过期的场景。
对应React实现代码
1. 改造登录页,存储token过期时间
JWT本身包含过期信息,登录时需要同时把token过期时间存入localStorage,方便后续校验:
export default function Signin() { const submitData = async (data)=>{ const apiData= await postSigninData(data) // 此处以接口返回token和expires_in(有效期单位为秒)为例,可根据实际接口结构调整 const token = apiData.data.token const expireTimestamp = Date.now() + apiData.data.expires_in * 1000 localStorage.setItem('token', token) localStorage.setItem('token_expire', expireTimestamp) } return ( <Box> <h1> Signin Page</h1> </Box> ) }
2. 编写ProtectedRoutes组件的自动登出逻辑
适配你当前使用的react-router v5版本的实现:
import { Redirect, Route } from 'react-router-dom' const ProtectedRoutes = ({ component: Component, ...rest }) => { // token有效性校验逻辑 const checkAuth = () => { const token = localStorage.getItem('token') const expireTime = localStorage.getItem('token_expire') // 无token直接判定未登录 if (!token || !expireTime) return false // 已过期则清除本地存储,判定未登录 if (Date.now() > Number(expireTime)) { localStorage.removeItem('token') localStorage.removeItem('token_expire') return false } return true } return ( <Route {...rest} render={props => checkAuth() ? ( <Component {...props} /> ) : ( // 未登录跳转登录页,携带当前页面路径,登录后可直接跳回原页面 <Redirect to={{ pathname: "/signin", state: { from: props.location } }} /> ) } /> ) } export default ProtectedRoutes
3. 可选:全局请求拦截器补充自动登出
如果需要处理用户停留在页面期间token过期的场景(比如长时间未操作,操作时调用接口才发现token过期),可以在axios响应拦截器中补充逻辑:
import axios from 'axios' axios.interceptors.response.use( response => response, error => { // 接口返回401未授权状态码时,触发登出逻辑 if (error.response?.status === 401) { localStorage.removeItem('token') localStorage.removeItem('token_expire') window.location.replace('/signin') } return Promise.reject(error) } )
内容的提问来源于stack exchange,提问作者ASIF KAIF
相关产品推荐
相关产品推荐

