Express-Session在REST Client运行正常但React站点跨路由读session为undefined
问题核心
express-session依赖Cookie中的connect.sid字段识别用户会话,REST Client作为接口测试工具不受浏览器同源策略限制,会自动携带Cookie;而React运行在浏览器中,跨域请求默认不会携带身份凭证,导致后端每次都拿到新的空会话,因此读取不到之前存储的session值。
解决方案
1. 修正后端CORS配置
在现有CORS配置中新增credentials: true字段,允许跨域请求携带凭证:
app.use(cors({ origin: ["http://localhost:3000"], methods: ["GET", "POST"], credentials: true // 新增配置 }));
注意:CORS的origin不能配置为
*,否则浏览器会拒绝携带凭证,你当前明确指定源地址的写法是符合要求的。
如果需要更稳定的会话控制,可以补充session的cookie配置:
app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { maxAge: 24 * 60 * 60 * 1000, // 会话有效期1天,按需调整 sameSite: 'lax', // 本地开发用lax即可,生产环境跨站部署时需设为none并开启secure secure: false // 本地http环境设为false,生产https环境设为true } }));
2. 修正前端React的请求配置
所有向后端发起的请求都需要开启携带凭证的开关,按你使用的请求工具选择对应配置:
- 原生fetch请求:
fetch('http://后端地址/api/users/auth/log-in/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', // 必须添加 body: JSON.stringify({username: '你的账号', password: '你的密码'}) })
- axios请求:
// 单次请求添加配置 axios.post('http://后端地址/api/users/auth/log-in/', { username: '你的账号', password: '你的密码' }, { withCredentials: true // 必须添加 }) // 也可以全局配置,避免每次请求重复添加 axios.defaults.withCredentials = true
3. 优化登录路由的session存储逻辑
req.session.save()是异步方法,你当前的写法没有等待存储完成就返回响应,极端情况会出现session未写入就返回,导致后续请求拿不到状态,调整为等待存储完成再返回:
router.post('/api/users/auth/log-in/', async (req, res) => { // ... 用户身份校验逻辑,此处生成布尔类型校验结果变量authenticated req.session.authenticated = authenticated; if (authenticated) req.session.user = req.body.username; // 等待session存储完成再返回 req.session.save((err) => { if (err) return res.status(500).json({success: false, msg: '会话存储失败'}); res.json({"success": true, "authenticated": authenticated}); }) });
内容的提问来源于stack exchange,提问作者Marcos
相关产品推荐
相关产品推荐

