You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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可能无法覆盖旧值,导致残留无效数据。

解决步骤

  1. 清除旧Cookie:打开浏览器开发者工具(F12),进入Application/Storage -> Cookies,找到对应域名下的userCookie并手动删除。
  2. 优化存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攻击
    });
    
  3. 验证序列化结果:添加日志确认存入的是有效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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:19:53