MERN Stack登录后Cookie用户信息解析失败问题及标准方案咨询
错误原因及解决方法
错误原因
控制台报错SyntaxError: "[object Object]" is not valid JSON,核心问题是user Cookie中存储的内容是无效的字符串"[object Object]",而非合法的JSON格式。常见触发场景:
- 旧Cookie残留:之前测试时直接将JavaScript对象(
response.data)存入Cookie,react-cookie会自动调用对象的toString()方法,导致存储值变为"[object Object]"。即使后续修改代码为JSON.stringify(response.data),旧Cookie未被清除或覆盖,读取时仍会解析无效字符串。 - Cookie参数冲突:若未设置
path、maxAge等参数,新Cookie可能无法覆盖旧值,导致残留无效数据。
解决步骤
- 清除旧Cookie:打开浏览器开发者工具(F12),进入
Application/Storage -> Cookies,找到对应域名下的userCookie并手动删除。 - 优化存Cookie逻辑:确保存入合法JSON字符串,同时配置完善的Cookie参数:
// 修改Login.jsx中的setCookie代码 setCookie("user", JSON.stringify(response.data), { path: "/", maxAge: 7 * 24 * 60 * 60 * 1000, // 7天有效期 secure: process.env.NODE_ENV === 'production', // 生产环境启用HTTPS sameSite: 'strict' // 防范CSRF攻击 }); - 验证序列化结果:添加日志确认存入的是有效JSON:
console.log("Serialized user data:", JSON.stringify(response.data));
MERN Stack标准登录认证实现方案
后端(Node.js + Express + MongoDB + JWT)
1. 用户模型定义
// models/User.js const mongoose = require('mongoose'); const bcrypt = require('bcryptjs'); const userSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true } }); // 密码哈希预处理 userSchema.pre('save', async function(next) { if (!this.isModified('password')) return next(); this.password = await bcrypt.hash(this.password, 10); next(); }); module.exports = mongoose.model('User', userSchema);
2. 登录接口实现
// routes/auth.js const express = require('express'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const User = require('../models/User'); const router = express.Router(); router.post('/login', async (req, res) => { try { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user) return res.status(400).json({ msg: '用户不存在' }); // 验证密码 const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) return res.status(400).json({ msg: '密码错误' }); // 生成JWT Token const token = jwt.sign( { id: user._id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '7d' } ); // 设置HttpOnly Cookie(推荐,防范XSS) res.cookie('token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', maxAge: 7 * 24 * 60 * 60 * 1000, sameSite: 'strict' }); // 返回脱敏用户信息 res.json({ _id: user._id, name: user.name, email: user.email }); } catch (err) { console.error(err); res.status(500).json({ msg: '服务器错误' }); } }); module.exports = router;
3. 认证中间件(保护私有接口)
// middleware/auth.js const jwt = require('jsonwebtoken'); const User = require('../models/User'); const auth = async (req, res, next) => { try { const token = req.cookies.token; if (!token) return res.status(401).json({ msg: '未授权,请登录' }); // 验证Token const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = await User.findById(decoded.id).select('-password'); // 排除密码字段 next(); } catch (err) { res.status(401).json({ msg: 'Token无效' }); } }; module.exports = auth;
前端(React)
1. 路由守卫(保护私有页面)
// components/ProtectedRoute.jsx import { Navigate, Outlet } from 'react-router-dom'; import { useCookies } from 'react-cookie'; const ProtectedRoute = () => { const [cookies] = useCookies(['token']); const isAuthenticated = !!cookies.token; return isAuthenticated ? <Outlet /> : <Navigate to="/login" />; }; export default ProtectedRoute;
2. 全局状态管理(Context API示例)
// context/AuthContext.jsx import { createContext, useContext, useEffect, useState } from 'react'; import { useCookies } from 'react-cookie'; import axios from 'axios'; const AuthContext = createContext(); export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [cookies] = useCookies(['token']); // 初始化用户信息 useEffect(() => { if (cookies.token) { axios.get('/api/v1/auth/me') .then(res => setUser(res.data)) .catch(() => setUser(null)); } }, [cookies.token]); return ( <AuthContext.Provider value={{ user, setUser }}> {children} </AuthContext.Provider> ); }; export const useAuth = () => useContext(AuthContext);
3. 登出逻辑
// Navbar.jsx中修改handleLogout const handleLogout = () => { removeCookie('token', { path: '/' }); removeCookie('user', { path: '/' }); setUser(null); // 同步全局状态 navigate('/login'); };
内容的提问来源于stack exchange,提问作者Tia Mat
相关产品推荐
相关产品推荐

