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

Node.js/Express API中JWT Token验证失败问题及通用方案咨询

问题描述

我正在开发基于Node.js/Express的API,目前已实现JWT Token生成功能,但在验证Token时遇到以下错误:

JsonWebTokenError: jwt malformed

当前代码如下:

const secretKey = 'mySecretKey';
const logins = async (req, res) => {
  const user = { id: 123, phoneNumber:'123XXXXXXXX' };
  // 创建JWT Token
  const token = jwt.sign(user, secretKey);
  res.json({ token });
}

function verifyToken(req, res, next) {
  const token = req.body.token;
  if (token) {
    const decode = jwt.verify(token, "secret");
    res.json({
      login: true,
      data: decode,
    });
  } else {
    res.json({
      login: false,
      data: "error",
    });
  }
}

我有两个问题:

  1. 如何创建适用于所有其他API的通用函数(Token不匹配时返回错误)?
  2. 如何正确验证Token?

解决方案

1. 正确验证Token的方法

你当前的验证错误核心有两个原因:

  • 生成Token用的密钥是mySecretKey,但验证时误用了"secret",密钥不匹配导致Token解析失败
  • 常规场景下客户端会把Token放在Authorization请求头(格式为Bearer <token>),而非请求体,从body取Token不符合规范,也容易因获取到错误内容触发jwt malformed

修正后的验证逻辑:

function verifyToken(req, res, next) {
  // 从Authorization请求头提取Token
  const authHeader = req.headers.authorization;
  const token = authHeader?.split(' ')[1]; // 拆分出Bearer前缀后的Token内容

  if (!token) {
    return res.status(401).json({
      login: false,
      data: "未提供有效Token"
    });
  }

  try {
    // 使用和生成Token时一致的密钥
    const decoded = jwt.verify(token, secretKey);
    // 将解析后的用户信息挂载到req对象,后续接口可直接调用
    req.user = decoded;
    // 验证通过,传递请求到下一个中间件/路由处理函数
    next();
  } catch (err) {
    // 针对性处理不同类型的Token错误
    let errorMsg = "Token验证失败";
    if (err.name === 'JsonWebTokenError') {
      errorMsg = "无效的Token";
    } else if (err.name === 'TokenExpiredError') {
      errorMsg = "Token已过期";
    }
    return res.status(401).json({
      login: false,
      data: errorMsg
    });
  }
}

2. 创建适用于所有API的通用验证中间件

上面的verifyToken已经是标准的Express中间件格式,可直接在需要验证的路由上使用,也能批量挂载到一组路由:

单路由使用示例

// 无需验证的登录接口
app.post('/login', logins);

// 需要验证的接口,将verifyToken放在路由处理函数前
app.get('/user/profile', verifyToken, (req, res) => {
  // 直接通过req.user获取解析后的用户信息
  res.json({
    login: true,
    data: req.user
  });
});

批量路由使用示例

如果某一组API都需要Token验证,可以用路由组批量挂载中间件:

const apiRouter = express.Router();
// 给整个路由组添加Token验证
apiRouter.use(verifyToken);

apiRouter.get('/orders', (req, res) => {
  res.json({ data: "用户订单列表", user: req.user });
});
apiRouter.post('/settings', (req, res) => {
  res.json({ msg: "设置保存成功", user: req.user });
});

// 将路由组挂载到主应用
app.use('/api', apiRouter);

核心注意点

  • 验证通过后必须调用next()传递请求,而非直接返回响应(验证失败除外)
  • 验证失败时返回401 Unauthorized状态码,符合HTTP规范
  • 将解析后的用户信息挂载到req.user,避免后续接口重复解析Token

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:15:08