使用React+Redux Toolkit与Axios实现会话过期自动登出
解决会话过期自动登出的可行方案
方案一:Axios响应拦截器(最直接高效)
利用你已封装的Axios实例,添加全局响应拦截器捕获401状态码,直接触发Redux的登出action,无需修改任何slice里的API逻辑。
实现代码
// 导入你的Axios实例、Redux store和登出action import axios from 'axios'; import store from '../store'; // 你的Redux store实例 import { logoutUser } from '../features/auth/authSlice'; // 已有的登出action // 初始化Axios实例 const api = axios.create({ baseURL: '/your-api-base-url', withCredentials: true }); // 响应拦截器:捕获401并触发登出 let isLoggingOut = false; // 防止多个401请求重复触发登出 api.interceptors.response.use( response => response, error => { if (error.response?.status === 401 && !isLoggingOut) { isLoggingOut = true; // 触发登出逻辑 store.dispatch(logoutUser()) .finally(() => { isLoggingOut = false; // 登出完成后重置标志 }); } // 继续抛出错误,让业务代码按需处理(可选) return Promise.reject(error); } ); export default api;
优势
- 零侵入:所有通过该实例发起的60个API都会自动被拦截,无需修改任何slice里的
createAsyncThunk代码 - 全局统一处理:包括未授权提示也可以在这里统一添加(比如全局toast),彻底消除冗余逻辑
方案二:Redux自定义中间件(纯Redux生态内处理)
如果不想让Axios直接依赖Redux store,可以编写自定义中间件,监听所有createAsyncThunk的失败action,判断是否为401错误后触发登出。
实现代码
// 自定义中间件文件:authErrorMiddleware.js import { logoutUser } from '../features/auth/authSlice'; const authErrorMiddleware = store => next => action => { // 匹配所有createAsyncThunk的失败action(格式为xxx/rejected) if (action.type.endsWith('/rejected')) { const error = action.error; // 根据你的API错误结构,判断是否为401未授权 if (error?.response?.status === 401) { // 避免重复触发登出 const { auth } = store.getState(); if (!auth.isLoggingOut) { store.dispatch(logoutUser()); } } } return next(action); }; export default authErrorMiddleware;
// 在configureStore中注册中间件 import { configureStore } from '@reduxjs/toolkit'; import authErrorMiddleware from './authErrorMiddleware'; export const store = configureStore({ reducer: { // 你的所有reducer }, middleware: getDefaultMiddleware => getDefaultMiddleware().concat(authErrorMiddleware) });
优势
- 完全遵循Redux数据流,Axios无需直接依赖store
- 可以在中间件中扩展更多全局错误处理逻辑
关键注意事项
- 重复触发防护:必须添加
isLoggingOut这类标志位,避免多个并发的401请求同时触发多次登出 - 登出action的异步处理:如果
logoutUser本身是异步action(比如需要调用后端登出接口),要确保在其执行期间不再处理新的401错误 - 错误信息统一提示:可以在拦截器/中间件中添加全局提示(如
alert('会话已过期,请重新登录')或UI组件库的toast),无需每个页面单独编写提示逻辑
内容的提问来源于stack exchange,提问作者Satyam
相关产品推荐
相关产品推荐

