Express.js JWT认证问题:LocalStorage有Token却提示未认证
问题核心原因
- 前端通过
Authorization: Bearer {token}请求头传递JWT,但后端verifyToken中间件从req.cookies.accessToken获取token,两者不匹配,导致token为undefined。 verifyUser中间件的权限逻辑错误:要求用户ID等于TourID才能评论,不符合业务逻辑(普通用户应可对任意旅游项目评论,无需ID匹配)。
解决方案
1. 修改后端verifyToken中间件,从请求头获取token
将原本从cookie取token的逻辑,改为解析Authorization头中的Bearer token:
const jwt = require("jsonwebtoken"); const verifyToken = (req, res, next) => { console.log("req.user:", req.user); console.log("req.params.tourId:", req.params.tourId); // 从Authorization头提取Bearer token const authHeader = req.headers.authorization; const token = authHeader && authHeader.split(' ')[1]; // 截取Bearer后的token部分 console.log("Token received in verifyToken:", token); if (!token) { return res.status(401).json({ success: false, message: "You are not authorized", }); } try { const user = jwt.verify(token, process.env.JWT_SECRET); console.log("Decoded User:", user); req.user = user; next(); } catch (error) { console.error("Token Verification Error:", error); res.status(401).json({ success: false, message: "Token is Invalid", }); } };
2. 修正verifyUser中间件的权限逻辑
普通用户只要登录即可提交评论,无需用户ID与TourID匹配,简化逻辑如下:
const verifyUser = (req, res, next) => { console.log("req.user:", req.user); console.log("req.params.tourId:", req.params.tourId); // 已登录用户(req.user存在)或管理员均可通过 if (req.user) { next(); } else { return res.status(401).json({ success: false, message: "You're not authenticated", }); } };
3. 可选:改用Cookie存储Token(优化方案)
如果希望后端从Cookie获取Token,需修改前端登录后的存储逻辑,将Token存入Cookie而非LocalStorage:
// 登录成功后示例代码 const accessToken = localStorage.getItem("accessToken"); // 将Token存入Cookie,设置有效期和作用域 document.cookie = `accessToken=${accessToken}; path=/; max-age=86400; SameSite=Lax`;
此时后端verifyToken中间件可保持原从Cookie取Token的逻辑,无需修改。
验证步骤
- 重启后端服务,应用修改后的中间件代码。
- 前端登录后提交评论,查看后端终端日志:
Token received in verifyToken应显示有效Token,Decoded User应显示解析后的用户信息。 - 提交评论接口应正常返回成功响应,不再触发未认证拦截。
内容的提问来源于stack exchange,提问作者user21744021
相关产品推荐
相关产品推荐

