React请求出现401 Unauthorized错误:添加Passport中间件后验证失败
问题分析与解决方案
Postman能正常通过身份验证但React端返回401,核心原因是跨域请求时React的fetch默认不会携带会话cookie,而Postman会自动保存并发送登录后的session cookie,导致Passport无法识别React端的登录状态。
1. 后端配置CORS允许凭证传递
首先安装并配置cors中间件,明确允许前端域名跨域请求,同时开启凭证支持:
const cors = require('cors'); // 替换为你的React前端地址,比如http://localhost:3000 const corsOptions = { origin: 'http://localhost:3000', credentials: true // 允许携带跨域凭证 }; // 注意:该中间件需放在session、passport和路由之前加载 app.use(cors(corsOptions));
同时调整session的cookie配置,适配跨域场景:
const sessionOptions = { secret: 'secretgoeshere', resave: false, saveUninitialized: false, cookie: { httpOnly: true, expires: Date.now() + 1000 * 60 * 60 * 24 * 7, maxAge: 1000 * 60 * 60 * 24 * 7, sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax', // 生产环境设为none,开发环境用lax secure: process.env.NODE_ENV === 'production' // 生产环境必须开启secure(依赖HTTPS) } };
2. 前端fetch请求添加凭证配置
修改你的useFetch钩子,强制请求携带凭证:
import { useState, useEffect } from 'react' const useFetch = (url, options = {}) => { const [data, setData] = useState(null) const [error, setError] = useState(null) const [loading, setLoading] = useState(true) useEffect(() => { const fetchData = async() => { try { // 合并默认的凭证配置,确保跨域请求携带cookie const fetchOptions = { credentials: 'include', ...options } const res = await fetch(url, fetchOptions) if (!res.ok) throw new Error(`请求失败:${res.status}`) const parsedData = await res.json() setData(parsedData) } catch (e) { setError(e); } finally { setLoading(false) } } fetchData() // eslint-disable-line react-hooks/exhaustive-deps }, [url, options]) return { data, error, loading } } export default useFetch
3. 检查后端中间件顺序
确保中间件加载顺序严格遵循:
CORS中间件 → Session中间件 → Passport初始化/会话中间件 → 请求体解析中间件(express/json、urlencoded) → 业务路由
你的现有代码中express.json()和urlencoded放在passport之后的顺序没问题,但必须保证CORS中间件在最前面。
验证步骤
- 登录后,在React开发者工具的
Application→Cookies中确认是否存在后端设置的session cookie - 发起请求时,在
Network面板查看Request Headers是否包含Cookie字段 - 后端打印
req.isAuthenticated()的值,确认是否能正确识别登录状态
内容的提问来源于stack exchange,提问作者MarkoS
相关产品推荐
相关产品推荐

