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
相关产品推荐
相关产品推荐

