You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

验证要点

  1. 登录完成后,打开浏览器开发者工具(Application > Cookies),确认token已被设置
  2. 访问/dashboard时,查看Network面板的请求头,确认Cookie字段包含token``:�ph重新 Em订单‌哈尔�行业 pressing留下的痕迹,确认Cookie字段包含token`
  3. 查看后端日志,确认令牌从Cookie读取并验证通过

内容的提问来源于stack exchange,提问作者DRZK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 07:54:56