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

React+Express实现JWT认证出现Cannot read property 'token' of undefined报错咨询

问题排查及解决方法

错误产生原因

  • Cookie读写逻辑理解错误:res.cookie()是将Cookie写入响应头返回给浏览器,仅会在后续客户端请求中被携带到服务端,本次请求的req.cookies是本次请求发起时浏览器携带的Cookie,刚设置完就从req.cookies读取必然返回undefined。
  • 缺少Cookie解析中间件:Express默认不会解析请求头中的Cookie,未安装配置cookie-parser中间件的情况下,req.cookies本身就是undefined,所有Cookie字段都无法读取。
  • 跨域配置不符合要求:前端运行在localhost:3000、后端运行在localhost:5000属于跨域场景,默认情况下浏览器不会写入跨域响应的Set-Cookie,也不会在跨域请求中自动携带Cookie;如果后端CORS配置未开启凭证支持、允许源配置为*,也会导致Cookie读写失败。
  • 登录接口重定向逻辑错误:跨域场景下res.redirect('/')是跳转到后端服务的根路径,和前端路由无关,会导致前端逻辑异常。
  • 前端fetch未配置凭证参数:默认fetch请求不会携带Cookie,必须显式配置credentials参数才会触发Cookie的读写和携带。

具体修复方案

  1. 安装配置Express基础中间件
    首先安装依赖:
    npm install cookie-parser cors
    
    在Express入口文件中引入并配置:
    const cookieParser = require('cookie-parser');
    const cors = require('cors');
    
    // 配置CORS,必须指定明确的前端源、开启凭证支持
    app.use(cors({
      origin: 'http://localhost:3000',
      credentials: true
    }));
    // 解析请求Cookie
    app.use(cookieParser());
    
  2. 修复登录接口逻辑
    app.post('/login',async (req,res)=>{
        const {login, pwd } = req.body
        const isUserExist = await User.findOne({login:login})
        if(!isUserExist){
            return res.status(400).json({msg: '账号不存在'})
        }
        const match = await bcrypt.compare(pwd,isUserExist.pwd)
        if(!match){
            return res.status(400).json({msg: '密码错误'})
        }
        const accessToken = createToken(user)
        // 配置Cookie属性,httpOnly可防止前端JS读取,降低XSS风险
        res.cookie("token",accessToken,{
            maxAge:60*60*24*30*1000,
            sameSite: 'Lax',
            httpOnly: true
        })
        // 不要用后端重定向,返回状态让前端自行跳转
        res.json({code: 0, msg: '登录成功'})
    })
    
  3. 给userData接口添加异常处理
    router.get("/userData",async (req, res) => {
        try {
          const accessToken = req.cookies["token"] 
          if(!accessToken) return res.status(401).json({msg: '未登录'})
          const validtoken = verify(accessToken,"jwt-secret")
          const user = await User.findOne({login:validtoken.login})
          res.send(user)
        } catch (err) {
          res.status(401).json({msg: '认证失效'})
        }
    });
    
  4. 修复前端fetch请求配置
    所有和后端交互的fetch请求都要添加credentials: 'include'配置,登录请求和用户数据请求都需要添加:
    takeUserData = async() =>{
        // 注意要写全后端接口地址,同时添加credentials配置
        const response = await fetch('http://localhost:5000/userData', {
          credentials: 'include'
        });
        const body = await response.json();
        if (response.status !== 200) {
          throw Error('1234') 
        }
        return body;
    }
    

内容的提问来源于stack exchange,提问作者GDTyka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 17:27:04