使用 JWT 时出错,还想将 JWT 令牌发送到其他 API
Posted
技术标签:
【中文标题】使用 JWT 时出错,还想将 JWT 令牌发送到其他 API【英文标题】:Getting error when using JWT, also want to send JWT token to other APIs 【发布时间】:2021-10-18 13:00:39 【问题描述】:我在 node js/express js 中实现 JWT:
这是我的代码:
const jwt = require('jsonwebtoken');
const secretCode = crypto.randomBytes(64).toString('hex');
const refreshCode = crypto.randomBytes(64).toString('hex');
function generateAccessTokens(user)
return jwt.sign(user, secretCode, expiresIn: '30m', );
function refreshAccessTokens(user)
return jwt.sign(user, refreshCode); //refresh code should never expire
function verifyToken(request, response, next)
//let's access the authorization header
const authHeader = request.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if(token === null || typeof(token) === "undefined")
//tell the user you do not have access
response.status(401).json(message: "Unauthorized Access!");
//if token is not null then
jwt.verify(token, secretCode, (error, user) =>
if(error) return response.status(403).json(message: "Forbidden Access:Token Expired!");
//if the user is verified
request.user = user;
next(); //move on
);
我通过包含 verifyToken 作为中间件来保护这条路线。 这是我收到错误的路线:
router.get('/list', verifyToken , (request, response) =>
try
let listRequestToken = request.token;
jwt.verify(listRequestToken, secretCode, (err, authData) =>
if(err)
response.status(403).json(message: `You do not have access $error`);
else
let myOTPCodeList = await otpCodeModel.find();
return response.status(202).json(myOTPCodeList, authData);
);
catch(error)
return response.status(400).json(message: `Error Occurred:\n$error`);
);
我收到 Postman 的“无法得到回复”。
在终端中得到以下错误:
"message": "You do not have access JsonWebTokenError: jwt must be provided"
问题 1: 如何解决上述错误?
问题 2: 将 jwt 令牌发送到其他 REST API 的最佳方式是什么?
【问题讨论】:
“必须提供jwt”错误来自哪里?编辑:哦,对,来自jwt.verify
- 猜测,let listRequestToken = request.token;
是undefined
,因为您正在发送请求标头(授权)并期望它在请求对象上作为token
属性...它将如何到达那里?
您正在将用户添加到请求中,但不是令牌 - 但如果 verifyToken
已经验证了令牌,则无需在 router.get 中再次验证
是的,你会知道它会验证 response
是否有 user
属性,当令牌已经验证时中间件 (verifyToken) 会放在那里
【参考方案1】:
function verifyToken(request, response, next)
//let's access the authorization header
const authHeader = request.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if(token === null || typeof(token) === "undefined")
//tell the user you do not have access
response.status(401).json(message: "Unauthorized Access!");
//if token is not null then
jwt.verify(token, secretCode, (error, user) =>
if(error) return response.status(403).json(message: "Forbidden Access:Token Expired!");
//if the user is verified
request.user = user;
next(); //move on
);
此代码已经在验证令牌,并设置request.user = user
然后你做:
let listRequestToken = request.token; // this will be undefined
jwt.verify(listRequestToken, secretCode, (err, authData) =>
if(err)
response.status(403).json(message: `You do not have access $error`);
else
let myOTPCodeList = await otpCodeModel.find();
return response.status(202).json(myOTPCodeList, authData);
);
此代码使用verifyToken
来验证令牌。如果经过验证,request
将具有 user
属性
token
属性绝不会添加到request
所以
-
您正在使用
undefined
令牌调用 jwt.verify
您无需再次致电jwt.verify
,因为它已经完成了
您需要使用request.get('Authorization')
访问标头
所以,只需将return
添加到response.status(401).json(message: "Unauthorized Access!");
function verifyToken(request, response, next)
//let's access the authorization header
const authHeader = request.get('Authorization'); // ****
const token = authHeader && authHeader.split(' ')[1];
if(token === null || typeof(token) === "undefined")
//tell the user you do not have access
return response.status(401).json(message: "Unauthorized Access!"); // ****
//if token is not null then
jwt.verify(token, secretCode, (error, user) =>
if(error) return response.status(403).json(message: "Forbidden Access:Token Expired!");
//if the user is verified
request.user = user;
next(); //move on
);
和
router.get('/list', verifyToken , (request, response) =>
try
if(!request.user)
response.status(403).json(message: `You do not have access $error`);
else
let myOTPCodeList = await otpCodeModel.find();
return response.status(202).json(myOTPCodeList, request.user);
catch(error)
return response.status(400).json(message: `Error Occurred:\n$error`);
);
jwt.verify
在verifyToken
中有一个名为user
的回调参数
jw.verify
在route.get
中有一个名为authData
的回调参数
当然,这两个结果是相同的数据,只是变量名不同,所以response.name
和你预期的authData
是一样的
【讨论】:
感谢您的回答,它告诉我“未经授权的访问!”,这意味着根据我的 verifyToken 函数它是未定义或为空 我的代码更改如何使错误更早发生?这太奇怪了 在const token = authHeader && authHeader.split(' ')[1];
之后添加一个console.log(token)
@abc123 我现在看到了最后一个问题 - 该错误可能已被掩盖,因为您没有 return response.status(401)
正如另一个答案所指出的那样
我回来了,但仍然,当我 console.log(token) 我得到未定义【参考方案2】:
如果标记为 null 或未定义,则缺少 return 关键字
function verifyToken(request, response, next)
//let's access the authorization header
const authHeader = request.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if(token === null || typeof(token) === "undefined")
//tell the user you do not have access
// return the response
return response.status(401).json(message: "Unauthorized Access!");
//if token is not null then
jwt.verify(token, secretCode, (error, user) =>
if(error) return response.status(403).json(message: "Forbidden Access:Token Expired!");
//if the user is verified
request.user = user;
next(); //move on
);
【讨论】:
好吧,我能想到的另一个解决方案是您正在访问 request.headers['authorization'] 但在 Postman 中,您将“授权”作为键。您的第一个字符大写以上是关于使用 JWT 时出错,还想将 JWT 令牌发送到其他 API的主要内容,如果未能解决你的问题,请参考以下文章
带有 JWT 令牌的 Spring Security 和 Websocket
使用密钥大小小于 2048 的 RSA 安全密钥创建 JWT 令牌时出错