当客户端未携带 jwt cookie 时,后端未及时响应会导致 fetch 请求一直处于 pending 状态;需显式检查 token 是否存在并返回明确状态码(如 401),避免请求无响应。
当客户端未携带 jwt cookie 时,后端未及时响应会导致 fetch 请求一直处于 pending 状态;需显式检查 token 是否存在并返回明确状态码(如 401),避免请求无响应。
在基于 JWT 的 Cookie 认证流程中,一个常见但容易被忽视的问题是:当 req.cookies.token 为空(即未设置 cookie)时,jwt.verify() 不会执行回调,也不会抛出同步错误,导致整个请求既不响应也不终止,最终在浏览器中表现为 fetch 请求长期处于 pending 状态。
根本原因在于 jwt.verify() 是异步操作,且仅在传入有效字符串 token 时才触发回调;若传入 undefined 或空字符串,它不会调用回调函数,而你的代码中又没有前置校验,因此 res.json() 和 res.status() 永远不会被执行,Node.js 响应流被挂起。
✅ 正确做法是:在调用 jwt.verify() 前,先严格校验 token 是否存在且为非空字符串:
import jwt from "jsonwebtoken";
export const isAuthenticated = (req, res) => {
const token = req.cookies?.token;
// ✅ 关键修复:主动检测 token 缺失
if (!token || typeof token !== 'string' || token.trim() === '') {
return res.status(401).json({
ok: false,
message: 'Authentication token was not provided.'
});
}
// ✅ 安全传递 token(已确保非空)
jwt.verify(token, process.env.SECRET, (err, user) => {
if (err) {
// 例如 token 过期、签名无效等
return res.status(403).json({
ok: false,
message: 'Invalid or expired token.'
});
}
// ✅ 验证成功,返回用户信息
res.status(200).json({ ok: true, user });
});
};⚠️ 注意事项:
- 不要依赖 res.json().status(200) 链式调用——res.json() 已自动结束响应,后续 .status(200) 无效且可能引发警告;
- 始终优先做输入校验(defense in depth),不能假设中间件或客户端一定提供合法字段;
- 前端 fetch 应设置超时(如 signal: AbortController.timeout(8000))并处理 401/403 状态,及时跳转登录页或清除本地状态;
- 生产环境建议使用 express-jwt 或 @ts-rest/express 等成熟库替代手写验证逻辑,提升安全性和可维护性。
通过增加 token 存在性校验,你不仅解决了 pending 问题,还使认证接口符合 HTTP 语义规范(401 Unauthorized 表示凭据缺失,403 Forbidden 表示凭据无效),显著提升前后端协作的健壮性与可观测性。


















