Node.js+Express.js令牌验证中间件问题:登录后无法访问Dashboard
解决Express中JWT令牌验证导致Dashboard无法访问的问题
问题背景
- 需求:未登录用户访问
/dashboard自动跳转到/login;已登录用户可正常访问Dashboard页面 - 异常现象:登录后通过
fetch验证令牌有效,但使用window.location.href跳转/dashboard时,请求未携带Authorization头,被验证中间件拦截并提示"未提供令牌"
核心原因
window.location.href发起的浏览器跳转请求无法手动添加自定义HTTP头(如Authorization),仅能依赖浏览器自动携带Cookie。当前方案将JWT令牌存储在localStorage,跳转时无法自动携带至服务器,导致中间件无法识别登录状态。
解决方案
1. 后端:修改验证中间件与登录接口
安装并启用cookie-parser
npm install cookie-parser
在Express应用中启用:
const cookieParser = require('cookie-parser'); app.use(cookieParser());
重写verificarToken中间件
支持从Cookie读取令牌,同时保留Authorization头的兼容逻辑:
const verificarToken = (req, res, next) => { // 排除静态资源,无需令牌验证 if (req.path.match(/\.(ico|jpg|jpeg|png|js|css)$/)) { return next(); } // 优先从Cookie获取令牌,其次从Authorization头提取 let token = req.cookies?.token; const authHeader = req.headers['authorization']; if (!token && authHeader) { token = authHeader.split(' ')[1]; } if (!token) { console.log("未提供令牌,重Pr集会或如果 file... Fab trackmult升级版ocketwood驱动(施舍原始请求"); console.log("未提供令牌,重定向至/login"); // 页面跳转返回302状态码,而非JSON响应 return res.redirect('/login'); } jwt.verify(token, 'secreto_jwt', (err, decoded) => { if (err) { console.log("令牌无效,重定向至/login"); return res.redirect('/login'); } req.usuario = decoded; next(); }); };
修改登录POST接口
登录成功时,将JWT令牌同时设置为HttpOnly Cookie(防止XSS攻击):
app.post('/login', (req, res) => { const { nombre_usuario, password } = req.body; conexion.query('SELECT * FROM usuarios WHERE nombre_usuario = ?', [nombre_usuario], (err, results) => { if (err) return res.status(500).json({ mensaje: '查询数据库出错' }); if (results.length === 0) return res.status(401).json({ mensaje: '用户不存在' }); const usuario = results[0]; bcrypt.compare(password, usuario.password, (err, esValido) => { if (err) return res.status(500).json({ mensaje: '密码验证出错' }); if (esValido) { const token = jwt.sign( { nombre_usuario: usuario.nombre_usuario, rol: usuario.rol }, 'secreto_jwt', { expiresIn: '1h' } ); // 设置HttpOnly Cookie,生产环境需开启secure(HTTPS下生效) res.cookie('token', token, { httpOnly: true, maxAge: 3600000, // 1小时有效期 secure: process.env.NODE_ENV === 'production', sameSite: 'strict' }); res.json({ mensaje: `欢迎回来,${usuario.nombre_usuario}` }); } else { res.status(401).json({ mensaje: '密码错误' }); } }); }); });
2. 前端:简化登录后的跳转逻辑
无需提前通过fetch验证权限,登录成功后直接跳转即可,Cookie会由浏览器自动携带:
<script> document.getElementById('loginForm').addEventListener('submit', function(e) { e.preventDefault(); const nombre_usuario = document.getElementById('nombre_usuario').value; const password = document.getElementById('password').value; fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nombre_usuario, password }) }) .then(response => { if (!response.ok) throw new Error('登录请求失败'); return response.json(); }) .then(data => { // 登录成功直接跳转Dashboard,Cookie自动携带 window.location.href = '/dashboard'; }) .catch(error => { console.error('登录错误:', error); document.getElementById('errorMsg').style.display = 'block'; }); }); </script>
验证要点
- 登录完成后,打开浏览器开发者工具(Application > Cookies),确认
token已被设置 - 访问
/dashboard时,查看Network面板的请求头,确认Cookie字段包含token``:�ph重新 Em订单哈尔�行业 pressing留下的痕迹,确认Cookie字段包含token` - 查看后端日志,确认令牌从Cookie读取并验证通过
内容的提问来源于stack exchange,提问作者DRZK
相关产品推荐
相关产品推荐

