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

Node.js中split读取undefined报错及token重新生成问题求助

解决TypeError及实现Token重新生成方案

一、解决Cannot read properties of undefined (reading 'split')错误

1. 根本原因

当请求头中不存在cookie字段时,直接调用req.headers.cookie.split(';')会触发undefined读取属性的错误。

2. 两种修复方案

方案1:手动添加存在性检查

在所有读取req.headers.cookie的方法(verifyToken、refreshToken、Logout)中,先判断cookie是否存在:

// 示例:verifyToken中间件修改
exports.verifyToken = (req, res, next) => {
  // 先检查cookie是否存在
  if (!req.headers.cookie) {
    return res.status(401).json({ message: '请先登录' });
  }
  // 再解析cookie
  const cookies = req.headers.cookie.split(';').reduce((acc, cookie) => {
    const [key, value] = cookie.trim().split('=');
    acc[key] = value;
    return acc;
  }, {});

  const accessToken = cookies.accessToken;
  if (!accessToken) {
    return res.status(401).json({ message: '缺少访问令牌' });
  }

  // 后续验证逻辑...
};

方案2:使用cookie-parser中间件(推荐)

这个中间件会自动解析请求头中的cookie,并存入req.cookies对象,无需手动split,彻底避免报错:

  • 安装依赖:
npm install cookie-parser
  • 在server.js中注册中间件:
const cookieParser = require('cookie-parser');
app.use(cookieParser());
  • 修改verifyToken等方法:
exports.verifyToken = (req, res, next) => {
  // 直接从req.cookies获取,不存在则为undefined
  const accessToken = req.cookies.accessToken;
  if (!accessToken) {
    return res.status(401).json({ message: '缺少访问令牌' });
  }

  // 后续验证逻辑...
};

二、实现Token重新生成(Refresh Token)功能

1. 核心流程

  • 从cookie中获取有效的refreshToken
  • 验证refreshToken合法性
  • 生成新的accessToken(可选生成新的refreshToken)
  • 将新的token写入cookie并返回给前端

2. 具体代码实现

在userController.js中编写refreshToken方法:

const jwt = require('jsonwebtoken');

exports.refreshToken = (req, res) => {
  // 使用cookie-parser后直接获取refreshToken
  const refreshToken = req.cookies.refreshToken;
  if (!refreshToken) {
    return res.status(401).json({ message: '缺少刷新令牌' });
  }

  // 验证refreshToken
  jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ message: '刷新令牌无效' });
    }

    // 生成新的accessToken(有效期15分钟)
    const newAccessToken = jwt.sign(
      { id: user.id, username: user.username },
      process.env.ACCESS_TOKEN_SECRET,
      { expiresIn: '15m' }
    );

    // 可选:生成新的refreshToken(有效期7天),替换旧令牌
    const newRefreshToken = jwt.sign(
      { id: user.id, username: user.username },
      process.env.REFRESH_TOKEN_SECRET,
      { expiresIn: '7d' }
    );

    // 将新的refreshToken写入cookie(配置安全参数)
    res.cookie('refreshToken', newRefreshToken, {
      httpOnly: true, // 防止前端JS读取,提升安全性
      secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS
      sameSite: 'strict', // 防止CSRF攻击
      maxAge: 7 * 24 * 60 * 60 * 1000 // 有效期7天
    });

    // 返回新的accessToken
    res.status(200).json({ accessToken: newAccessToken });
  });
};

在userRouter.js中添加refreshToken路由:

const express = require('express');
const router = express.Router();
const userController = require('./userController');

// 刷新令牌路由
router.post('/refresh-token', userController.refreshToken);

// 其他路由...
module.exports = router;

前端配合逻辑

当前端收到401(accessToken过期)时,调用/refresh-token接口获取新的accessToken,之后用新token继续请求接口。

三、Logout方法的完善

确保Logout时清除相关cookie:

exports.logout = (req, res) => {
  // 清除accessToken和refreshToken cookie
  res.clearCookie('accessToken');
  res.clearCookie('refreshToken');
  res.status(200).json({ message: '退出登录成功' });
};

内容的提问来源于stack exchange,提问作者ASNA V A

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:25:30