Node.js服务端调用req.header()无法获取指定请求头值异常排查
问题说明
本问题关联此前遇到的JsonWebTokenError: jwt must be a string报错:在Node.js服务端执行console.log(req.header('host'),'req host')读取host请求头时,打印结果和直接打印req得到的完整请求对象一致,无法正常读取请求头指定字段,已配置CORS允许自定义请求头访问但问题未解决。
相关代码
前端Post.js(发起POST请求携带请求头)
import React, { useEffect, useState } from 'react' import { useParams } from 'react-router-dom'; import axios from 'axios'; import './Post.css' function Post() { let { id } = useParams(); const [postObject, setPostObject] = useState({}) const [comments, setComments] = useState([]); const [newComment, setNewComment] = useState(""); const addComment = () => { const accessToken = sessionStorage.getItem('accessToken') console.log(typeof (accessToken), 'acces token in comment button') axios.post(`http://localhost:4000/comments`, { commentBody: newComment, PostId: id }, { headers: { accessToken: accessToken, } } ) .then((res) => { const data = res.data; console.log(data, 'comments') setComments([...comments, data]) setNewComment("") }) .catch((err) => { alert(err, 'Error:comment') }) } return ( <div className='Post'> <div className='left__side'> <div className='left__side__wrapper'> <div className='title'>{postObject.title}</div> <div className='text'>{postObject.postText}</div> <div className='username'>{postObject.username}</div> </div> </div> <div className='right__side'> <div className='right__side__wrapper'> <div className='add__comment__container'> <input type="text" value={newComment} placeholder="Comment" onChange={(e) => setNewComment(e.target.value)} /> <button onClick={addComment}> Submit Comment</button> </div> <div className='listOfCommnets'> {comments.map((item, index) => { return <div className='comments' key={index}>Comments:<br />{item.commentBody}</div> })} </div> </div> </div> </div> ) } export default Post
后端AuthMiddleware.js(接收请求头的中间件)
const { verify } = require("jsonwebtoken") const validateToken = (res, req, next) => { console.log(req, 'req') console.log(req.header('host'), 'req host') } module.exports = { validateToken }
问题根因
Express 中间件的形参顺序是固定的,必须按照 (请求对象Request, 响应对象Response, next回调) 的顺序定义。你当前中间件写的形参顺序是(res, req, next),导致:
- 形参名
res实际接收到的是真实的请求对象 - 形参名
req实际接收到的是真实的响应对象
响应对象本身没有读取请求头的header()方法,调用时自然返回不符合预期的结果,后续读取token做校验时也会拿不到字符串格式的jwt,触发之前的报错。
修复方法
调整中间件的形参顺序即可,修正后的中间件代码如下:
const { verify } = require("jsonwebtoken") const validateToken = (req, res, next) => { console.log(req.header('host'), 'req host') // 后续jwt校验逻辑可正常编写 const accessToken = req.header("accessToken"); if (!accessToken) return res.status(401).json({error: "未授权访问"}); try { const userInfo = verify(accessToken, "你配置的jwt签名密钥"); req.user = userInfo; next(); } catch (err) { return res.status(403).json({error: "token校验失败"}); } } module.exports = { validateToken }
补充说明
- 你之前配置的CORS规则没有问题,修复参数顺序后自定义的
accessToken请求头可以被正常读取 - 修复后即可拿到字符串格式的token,不会再触发
JsonWebTokenError: jwt must be a string报错
内容的提问来源于stack exchange,提问作者Sharanjeet Singh
相关产品推荐
相关产品推荐

