Node.js中使用JWT访问受保护路由报ERR_HTTP_HEADERS_SENT错误如何解决
问题诊断与修正方案
核心问题说明
出现ERR_HTTP_HEADERS_SENT错误的直接原因是:auth.js的JWT校验逻辑中,校验出错返回响应后没有终止代码执行,后续仍然调用了next()触发路由逻辑再次发送响应,导致重复设置响应头报错。
除此之外还存在3个隐含问题:
- 生成JWT和校验JWT使用的密钥不一致:
server.js生成JWT用的是字符串"mypassphrase",auth.js校验时读取的是private.pem文件内容,两者不匹配会导致JWT永远校验失败 /jwt接口生成token后仅在控制台打印,没有返回给客户端,无法正常获取token用于后续请求- HS256是对称加密算法,不需要读取pem密钥文件,直接使用统一的字符串密钥即可,多余的文件读取会增加不必要的开销
修正代码
1. server.js修正
const express = require('express'); const jwt = require('jsonwebtoken'); const authorize = require('./auth'); const chalk = require('chalk'); const app = express(); // 统一JWT密钥,实际项目建议放在环境变量中 const JWT_SECRET = "mypassphrase"; const port = 3000 || process.env.PORT; app.get('/',(req,res) => { res.send("Home page"); }); app.get('/jwt',(req,res) => { let token = jwt.sign({"body":"stuff"}, JWT_SECRET,{ algorithm: 'HS256'}); console.log(chalk.blue(token)); // 新增:将生成的token返回给客户端 res.json({token}); }); app.get('/sec',authorize,(req,res) => { res.json({"name":"Hello digi"}); }); app.listen(port,() => { console.log(chalk.green(`App is running at ${port}`)); });
2. auth.js修正
const jwt = require('jsonwebtoken'); // 和生成端保持一致的JWT密钥 const JWT_SECRET = "mypassphrase"; const authorize = (req,res,next) => { if(typeof req.headers.authorization !== "undefined"){ let token = req.headers.authorization.split(" ")[1]; jwt.verify(token, JWT_SECRET,{ algorithm: "HS256" },(err,user) => { if (err) { // 出错后直接return终止执行,不会再调用next return res.json({ error: "Not Authorized" }); } // 仅校验通过时才调用next进入后续路由逻辑 return next(); }); } else { return res.json({ error: "No Authorization header" }); } } module.exports = authorize;
内容的提问来源于stack exchange,提问作者Digvijay Singh Thakur
相关产品推荐
相关产品推荐

