【问题标题】:JWT token cannot be set to header (Node & express.js)JWT 令牌不能设置为标头(Node 和 express.js)
【发布时间】:2021-11-28 14:47:43
【问题描述】:

我正在开发一个使用 MongoDB 作为其数据库的 Node 后端。当我应该在响应标头中发送我的 JWT 令牌时,我收到一个错误,即标头在发送到客户端后无法设置。这是我的 POST 请求:

api.post("/account/create", async (req, res) => {

    // Hash the password using bcrypt
    const hashedPassword = await bcrypt.hash(req.body.password, 10);

    // Store new login credentials
    const user = {
        username: req.body.username,
        password: hashedPassword
    };

    // Create a new JWT token
    const token = jwt.sign({ username: req.body.username }, secret);

    // Search for a matching username from the database
    await logincollection.findOne(user, (err, result) => {

        // If username was not found, add the credentials to the database
        if (result == null) {

            // Insert the credentials to the login credentials collection
            logincollection.insertOne(user, (err, result) => {

                // If an error occurred, return code 404 to the client
                if (err) {
                    res.status(404).send();
                }

            })

            // Create personal collection for the user
            userdb.createCollection(JSON.stringify(user.username), (err, result) => {

                // If an error occurred, return code 404 to the client
                if (err) {
                    res.status(404).send();
                }

            })

            // Return code 200 (success)
            res.status(200).send({ auth: true, token: token });

        } else {

            // If username was found, return code 400 to the client
            res.status(400).send();

        }

    })

})

当我尝试在另一个 POST 请求中获取令牌值时,它返回 undefined:

api.post("/account/login", async (req, res) => {

    // User object
    const user = {
        username: req.body.username,
        password: req.body.password
    };

    const token = req.headers["token"];
    console.log(token);

    // Get username as a string
    const username = JSON.stringify(user.username);

    // Get hashed password from the collection
    const hashedPassword = await logincollection.findOne({ username: req.body.username });
    console.log(hashedPassword);

    // Search for matching login credentials
    await logincollection.find(user, (err, result) => {

        // If no token was given
        if (!token) {

            // Return code 401 to the client
            res.status(401).send();

        }

        // Verify the given JWT token
        jwt.verify(token, secret, (err, decoded) => {

            // If verification failed
            if (err) {

                // Return code 500 to the client
                res.status(500).send();

            }

            // Return code 200 and decoded token to the client
            res.status(200).send(decoded);

        })

            // Use bcrypt to compare the passwords and authenticate login
            bcrypt.compare(req.body.password, hashedPassword).then(match => {

                // If the credentials match
                if (match) {

                    // Return the result as an object
                    const sendObject = {
                        username: result.username,
                        password: result.password
                    };

                    // Return code 200 to the client
                    res.status(200).send(sendObject);

                    // Log to console when user logs in
                    console.log("User " + username + " logged in");

                // If the credentials do not match
                } else {

                    // Return code 404 to the client
                    res.status(404).send();

                }

            // If comparing fails
            }).catch(error => {

                // Return coe 500 to the client
                res.status(500).send();

            })

    })

})

我很确定解决方案非常简单,但我似乎无法解决这个问题,尽管我已经做了很多研究。

以下是 /account/create 请求返回给客户端的响应:

{
    "auth": true,
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QyIiwiaWF0IjoxNjMzNzg3MjE2fQ.duo5R9wXpk2Gj-iPHFMaDgKK0p3h6WZf5vnXrZViePo"
}

编辑:原来令牌没有进入标题,而是进入正文。我需要做些什么不同的事情才能将它传递给标题?

【问题讨论】:

  • 你确定调用“/account/create” API 200状态的结果会正确返回token吗?
  • 请分享与在标头中设置令牌相关的客户端代码。您还可以通过检查 API 调用并检查其标头在 chrome 网络选项卡中检查这一点。令牌是否通过 API 调用正确附加和发送?
  • @novonimo 我对问题进行了一些编辑,包括登录请求的其余部分和 /account/create 请求给出的响应
  • 如前所述请添加客户端相关代码
  • @novonimo 客户端相关代码是什么意思?这个前端是一个安卓应用,你是说那个代码吗?

标签: node.js express mongodb-query


【解决方案1】:

好吧,看来我理解错了。

我认为必须始终在标头中返回和接收令牌。不是这种情况。来自 /account/create 的令牌响应必须在正文中。在触发 /account/login 请求(验证登录)时,令牌必须仅设置为标头。

希望这可能对将来有同样问题的人有所帮助。

【讨论】:

    【解决方案2】:

    在result == null 的情况下,您有三个发送响应的语句:两个异步res.status(404) 语句和一个同步res.status(200) 语句。每个请求只能执行其中的一个。

    但是对于当前代码,每个请求都会执行状态 200 语句,即使失败的数据库操作稍后会导致额外的状态 404 语句,从而导致观察到的错误。 p>

    【讨论】:

    • 我修改了代码,只有在所有数据库操作成功完成后才返回响应码200,但最终结果是一样的。
    猜你喜欢
    • 2017-02-07
    • 1970-01-01
    • 2017-04-21
    • 2021-11-04
    • 2018-07-08
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 2017-05-20
    相关资源
    最近更新 更多