MERN栈应用如何读取Cookie中JWT令牌实现刷新页面保持用户登录状态
问题根因
你当前的登录状态(userInfo)存储在Redux的内存状态中,页面刷新后内存会被清空,Redux状态重置就会出现登录失效的假象,实际Cookie中的JWT仍然有效,只要在页面初始化时主动校验JWT并拉取用户信息即可恢复登录状态。
提示:不推荐将用户信息存储在localStorage等前端持久化存储中,容易遭受XSS攻击泄露敏感信息,通过后端校验JWT拉取信息是更安全的实现方式。
解决方案步骤
步骤1:新增后端校验接口与前端请求
后端新增无需额外传参的用户信息查询接口,例如GET /api/v1/users/me,接口逻辑为读取请求携带的Cookie中的JWT,校验有效后返回对应用户的基础信息(用户名、ID、权限等),校验失败则返回401状态码。
前端新增对应的异步请求:
// 在你存储loginUser的同个slice文件中添加 export const getCurrentUser = createAsyncThunk( 'users/getCurrentUser', async () => { const { data } = await API.get('/api/v1/users/me'); return data; } );
步骤2:适配Redux slice逻辑
在userLogin对应的slice中,新增getCurrentUser异步请求的状态处理:
pending状态:设置加载标识,避免路由守卫误判跳转fulfilled状态:将返回的用户信息存入userInfo,和loginUser成功的处理逻辑保持一致rejected状态:清空userInfo,可选抛出过期提示
步骤3:全局初始化触发校验
在应用的根组件(如App.jsx、main.jsx)中添加初始化逻辑,页面加载时自动触发用户信息拉取:
import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { getCurrentUser } from './store/userSlice'; // 替换为你的slice实际路径 function App() { const dispatch = useDispatch(); useEffect(() => { dispatch(getCurrentUser()); }, [dispatch]); // 原有App逻辑 }
步骤4:适配路由守卫逻辑
如果你的项目配置了登录拦截的路由守卫,需要新增加载状态判断:在getCurrentUser请求未完成前,先渲染加载占位UI,不要直接跳转到登录页,等请求完成后再根据userInfo是否存在判断是否放行。
现有代码优化提示
你当前的loginUser异步请求存在参数传递错误:createAsyncThunk的payload参数仅支持接收单个值,你当前写的async (email, password)会导致调用时password参数丢失,需要修改为传递对象:
// 修改后的loginUser export const loginUser = createAsyncThunk( 'users/loginUser', async ({email, password}) => { // 改为接收单个对象参数 const config = { headers: { 'Content-Type': 'application/json', }, }; // 你已经在API实例配置了baseURL,无需重复写完整域名 const { data } = await API.post( '/api/v1/users/login', { email, password }, config ); return data; } ); // 对应的调用逻辑也要修改 const submitHandler = e => { e.preventDefault(); dispatch(loginUser({email, password})); // 传入对象 };
内容的提问来源于stack exchange,提问作者valkkorn
相关产品推荐
相关产品推荐

