MERN应用中前端调用验证接口时JWT Token返回undefined问题
问题:MERN应用中JWT前端验证返回Token undefined的排查
我在MERN应用中使用JWT Token进行身份验证,通过Postman调用登录接口http://127.0.0.1:1000/api/v1/users/login登录用户后,再调用验证接口http://127.0.0.1:1000/api/v1/users/verify时Token可正常返回。但在React前端执行相同操作时,Token返回undefined(Token存储在Cookie中)。以下是我的React代码和Express端的Token验证代码,请问问题出在哪里?
React代码
function Welcome() { const [user, setUser] = useState(""); const sendRequest = async () => { const res = await axios .get("http://127.0.0.1:1000/api/v1/users/verify", { withCredentials: true, }) .catch((err) => console.log(err)); const data = await res.data; console.log("RESPONSE", data); return data; }; React.useEffect(() => { sendRequest().then((data) => console.log(data)); }, []); console.log(user); return <div>Welcome</div>; }
Express端验证Token代码
exports.verifyToken = async (req, res, next) => { const cookies = await req.headers.cookie; const token = cookies.split("=")[1]; if (!token) { res.status(404).json({ message: "no token found" }); } jwt.verify(String(token), process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(400).json({message: "Invalid token" }); } req.id = user.id; }); next(); };
问题分析与解决方案
1. Express端核心问题
await req.headers.cookie无意义且出错:req.headers.cookie是同步属性,不是Promise,加await会导致cookies变为undefined,后续split操作直接报错。- 未处理
cookies不存在的情况:如果浏览器没传Cookie,cookies.split会抛出Cannot read property 'split' of undefined错误,直接导致请求失败。 - 错误响应后未终止流程:
if (!token)返回响应后,代码仍会执行next(),导致后续逻辑混乱。 - 异步回调导致
next()提前执行:jwt.verify是异步回调,next()会在验证完成前执行,后续路由无法获取req.id。
2. 修正后的Express验证代码
exports.verifyToken = async (req, res, next) => { const cookies = req.headers.cookie; // 移除不必要的await // 先判断Cookie是否存在 if (!cookies) { return res.status(404).json({ message: "no token found" }); } const token = cookies.split("=")[1]; if (!token) { return res.status(404).json({ message: "no token found" }); } try { // 使用Promise版本的jwt.verify,确保验证完成后再执行next const user = await jwt.verify(String(token), process.env.JWT_SECRET); req.id = user.id; next(); } catch (err) { return res.status(400).json({ message: "Invalid token" }); } };
3. 额外必要配置
- CORS跨域配置:后端必须允许前端跨域携带凭证,否则浏览器不会发送Cookie:
const cors = require('cors'); app.use(cors({ origin: "http://localhost:3000", // 替换为你的前端实际地址 credentials: true }));
- 登录接口Cookie设置:设置Cookie时需配置正确的属性,确保浏览器能正常存储并携带:
// 登录成功后设置Cookie的示例 res.cookie("token", generatedToken, { httpOnly: true, // 防止XSS攻击 secure: process.env.NODE_ENV === "production", // 生产环境开启(需HTTPS) sameSite: "Lax", // 适配跨域场景,若完全跨域可设为"None"并配合secure maxAge: 24 * 60 * 60 * 1000 // Cookie有效期1天 });
4. React端检查点
- 确保登录请求也设置了
withCredentials: true,否则浏览器不会保存登录接口返回的Cookie:
// 登录请求示例 await axios.post("http://127.0.0.1:1000/api/v1/users/login", loginData, { withCredentials: true });
内容的提问来源于stack exchange,提问作者oladimeji
相关产品推荐
相关产品推荐

