【问题标题】:Getting error when using JWT, also want to send JWT token to other APIs使用 JWT 时出错,还想将 JWT 令牌发送到其他 API
【发布时间】: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) 会放在那里

标签: javascript node.js express jwt postman


【解决方案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

所以

  1. 您正在使用 undefined 令牌调用 jwt.verify
  2. 您无需再次致电jwt.verify,因为它已经完成了
  3. 您需要使用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 中,您将“授权”作为键。您的第一个字符大写
猜你喜欢
  • 2020-10-01
  • 2021-01-31
  • 2019-06-03
  • 2015-02-10
  • 2018-10-29
  • 2019-08-08
  • 1970-01-01
  • 2019-01-06
  • 2023-03-27
相关资源
最近更新 更多