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

Express.js中间件中JWT令牌验证出现'invalid signature'错误求助

JWT签名无效问题排查与解决

我正在开发一个使用JWT进行身份认证的Express.js应用,该认证与验证配置在Postman中运行正常,但从前端发起请求时,后端控制台出现以下错误:

JsonWebTokenError: invalid signature
    at C:\Users\lanci\node_modules\jsonwebtoken\verify.js:133:19  
    at getSecret (C:\Users\lanci\node_modules\jsonwebtoken\verify.js:90:14)
    at module.exports [as verify] (C:\Users\lanci\node_modules\jsonwebtoken\verify.js:94:10)
    at authMiddleware (file:///C:/Users/lanci/Desktop/Application_MyTicket/Admin_Dashboard/React-CRUD-Operation/organisateur_backend/middleware/auth.js:21:25)

以下是authController.js中的JWT令牌生成代码:

import jwt from "jsonwebtoken";

const generateToken = (user) => {
    return jwt.sign(
        { id: user.id, role: user.role },
        process.env.JWT_SECRET,
        { expiresIn: "1h" }
    );
};

// Example usage in login
const login = async (req, res) => {
    // User authentication logic
    const token = generateToken(user);
    res.json({ token });
};

我已确认以下几点:

  • process.env.JWT_SECRET在server.js和auth.js中均已正确加载;
  • 令牌在Postman中可正常使用,但前端请求时验证失败;
  • 将令牌粘贴到jwt.io中,签名显示为无效;
  • 重启服务器并重新生成令牌无法解决问题。

请问该错误的原因是什么?如何确保令牌验证在Postman和前端中都能正常工作?


错误原因分析

  1. 前端令牌传递格式不规范
    最常见的问题是前端在Authorization请求头中携带令牌时,未遵循Bearer <token>的标准格式,比如直接传入令牌字符串而省略Bearer 前缀,或者额外添加了空格、引号等冗余字符,导致后端读取的令牌内容异常。

  2. 令牌存储/传输过程被篡改
    比如使用localStorage存储令牌时误做了转义、截断操作,或通过URL参数传递令牌(易被编码/截断),导致后端收到的令牌与原始生成的令牌不一致。

  3. 密钥一致性问题
    尽管确认了环境变量已加载,但可能存在生成令牌与验证令牌时使用的JWT_SECRET值不一致的情况:比如服务器启动时部分模块提前加载,环境变量未完全初始化,导致生成令牌用了旧值/空值,验证时用了正确密钥。

解决方法

  1. 规范前端令牌传递格式
    前端发送请求时,Authorization头必须严格遵循Bearer <token>格式:

    // Axios请求示例
    axios.get('/api/protected', {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('authToken')}`
      }
    });
    

    后端中间件需正确提取令牌:

    // auth.js中间件示例
    const authMiddleware = (req, res, next) => {
      const authHeader = req.headers.authorization;
      if (!authHeader || !authHeader.startsWith('Bearer ')) {
        return res.status(401).json({ message: 'Unauthorized' });
      }
      const token = authHeader.split(' ')[1];
      jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
        if (err) return res.status(403).json({ message: 'Invalid token' });
        req.user = decoded;
        next();
      });
    };
    
  2. 排查令牌存储与传输环节

    • 禁止通过URL参数传递令牌,始终使用Authorization头;
    • 存储令牌时直接保存原始字符串,不做额外处理:
      // 登录成功后存储令牌
      localStorage.setItem('authToken', response.data.token);
      
    • 发送请求前直接读取存储的令牌,避免拼接或修改。
  3. 确认密钥完全一致

    • 在生成令牌和验证令牌的代码中分别打印process.env.JWT_SECRET,检查值的大小写、特殊字符、空格是否完全一致;
    • 检查.env文件中的JWT_SECRET是否存在多余空格或换行,比如不要写成JWT_SECRET= mysecret(前缀有空格);
    • 服务器启动时先打印process.env.JWT_SECRET,确认加载正确后再启动服务。
  4. 验证令牌完整性

    • 前端发送请求前,将令牌复制到jwt.io中验证签名;若此时签名无效,说明生成令牌时密钥已异常,检查generateToken函数中process.env.JWT_SECRET的加载时机;
    • 对比后端返回的令牌和前端存储的令牌,确认两者完全一致。

内容的提问来源于stack exchange,提问作者Lance-Legrand NGANDO-DAVID

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:53:12