
当 jwt 认证接口未收到有效 cookie 时,若未显式返回响应,express 会一直等待结束,导致前端 fetch 请求持续 pending;需在 token 缺失时主动返回 401 响应。
当 jwt 认证接口未收到有效 cookie 时,若未显式返回响应,express 会一直等待结束,导致前端 fetch 请求持续 pending;需在 token 缺失时主动返回 401 响应。
在基于 JWT 的 Cookie 认证流程中,isAuthenticated 中间件的核心职责是校验请求是否携带合法令牌,并及时反馈校验结果。然而,原始代码存在一个关键缺陷:未处理 req.cookies.token 为空(undefined 或空字符串)的情况。此时 jwt.verify() 不会被调用,回调函数永不执行,Express 响应对象(res)也未被终结——这将导致 HTTP 连接保持打开状态,前端 fetch 请求无限等待,最终表现为“pending”。
正确的做法是在调用 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.'
});
}
jwt.verify(token, process.env.SECRET, (err, user) => {
if (err) {
// ❗ 注意:403(Forbidden)适用于 token 存在但无效(如过期、签名错误)
return res.status(403).json({
ok: false,
message: 'Invalid or expired token.'
});
}
// ✅ token 有效,返回用户信息
res.status(200).json({ ok: true, user });
});
};
此外,还需注意以下实践要点:
- 状态码语义准确:401 Unauthorized 表示“未认证”(缺少凭证),403 Forbidden 表示“已认证但无权限”,二者不可混用;
- Cookie 安全配置一致性:确保 logout 路由清除 Cookie 的选项(secure, sameSite, httpOnly)与登录时设置的完全一致,否则可能因策略不匹配导致清除失败;
- 前端容错处理:fetch 请求应设置超时(如 AbortSignal.timeout(8000)),避免因服务端遗漏响应而长期阻塞 UI;
- 环境变量校验:上线前务必确认 process.env.SECRET 已正确加载,否则 jwt.verify() 会抛出同步异常,触发未捕获错误(需配合 Express 全局错误中间件处理)。
通过以上改进,可彻底解决空 Cookie 引发的 pending 问题,提升认证链路的健壮性与可观测性。











