使用 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.verifyverifyToken 中有一个名为user 的回调参数

jw.verifyroute.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

尝试使用 .NET JWT 库生成令牌时出错

使用密钥大小小于 2048 的 RSA 安全密钥创建 JWT 令牌时出错

使用 jwt 令牌时如何发送用户信息?

使用密钥大小小于2048的RSA安全密钥创建JWT令牌时出错

使用 JWT 获取令牌而不尝试用户凭据 Laravel?