【问题标题】:Where does json web token save the data?json web token 将数据保存在哪里?
【发布时间】:2017-06-23 12:58:54
【问题描述】:

我有一个使用 json 网络令牌的节点应用程序:

var jwt = require('jsonwebtoken');

如果登录成功,则此库以这种方式创建令牌:

var payload = {mydata: 'abcd'};
var token = jwt.sign(payload, 'secret', {
    expiresIn: 28800
});

return {
    success: true,
    message: 'Success',
    token: token
};

我不明白令牌在服务器上的存储位置。 如果收到令牌的同一用户调用受保护的资源,那么我有这一行:

jwt.verify(token_sent_by_used, 'secret', function (err, res) {
    if(!err){
        res.json({result: 'success'});
    }
    else{
        res.json({result: 'failure'});
    }
}

我问这个的原因是我找不到在多台机器上运行应用程序时如何处理 jwt 的解释。 如果我的后端放在不同的机器上并且用户向负载均衡器发出请求,那么该请求可以到达任何机器。 如果 jwt 在文件系统上写入令牌数据,那么我猜如果请求命中的机器不是创建令牌的机器,则可能会出现问题。 使用会话时,您可以将会话处理程序设置为数据库。你如何用 jwt 解决这个问题?

****编辑****

好的,让我们举个例子。 我有一个在机器 .10 上运行的节点应用程序,并且同一节点应用程序也在机器 .11 上运行。两台不同的机器。

我去机器 .10 并发送用户名密码。机器 .10 上的应用程序检查用户名/密码。他们都还好。机器 .10 创建一个 jwt 令牌并将其发送给我。

我现在向机器 .11 发出 curl 请求(向需要有效 jwt-token 的资源)发送机器 .10 宝贵发送给我的 jwt-token。机器 .11 不会抱怨 jtw-token 吗?它会被认为是有效的吗?即使它不是在机器 .11 上创建的?

【问题讨论】:

  • Jwt 令牌未存储在服务器上。创建 jwt 令牌服务器后,将该令牌发送给用户/浏览器。然后,您可以将该令牌保存到应用状态、浏览器的本地存储或浏览器的会话存储中。
  • 请查看已编辑的问题。
  • Jwt 令牌与机器无关。您只需要在两台机器上使用相同的密钥来解密/加密令牌。
  • Jwt 令牌只是用特定密钥加密的一些数据。只要某台机器有那个密钥,它就可以解密它。

标签: node.js jwt


【解决方案1】:

您问题中的两台服务器都必须能够验证令牌 - 它们必须能够生成签名。如果两个服务器共享相同的密钥(用于最初在 .10 上生成令牌的签名),那么两者都能够验证其内容。

在下面的截图中,红色部分和紫色部分都是明文——任何人都可以阅读和修改它们。然而,蓝色部分是特殊的——它只能在服务器上生成,红色和紫色部分,使用秘钥。所以,它保证了红色和紫色部分没有被篡改。

因此,当您将整个 JTW​​ 发送回服务器时,它可以使用密钥生成蓝色部分,并将其与您发送的蓝色部分进行比较。如果它们不匹配,则有人(非法)更改了红色或紫色部分,因此身份验证被拒绝。

【讨论】:

    【解决方案2】:

    JWT 不存储在服务器上。

    当您的服务器分发 JWT 时,它会为客户端提供一个访问者通行证,该通行证可以在它请求资源时使用。只要客户端持有它,并且它保持有效(即没有过期),它就可以将它与请求一起显示给服务器,服务器会做出相应的响应。

    服务器知道这是一个有效的通行证,因为它用它的秘密签名。

    至于在多台机器上运行,只要需要验证令牌的任何服务器知道秘密,就可以这样做。

    编辑以澄清上述内容

    您是在特别询问机器 A 是否会接受机器 B 颁发的令牌。

    接受令牌的唯一要求是验证签名,以便您可以验证它的来源。

    如果机器 A 和机器 B 共享秘密,则它们的令牌可以互换。两者完全没有区别,机器 A 无法判断是它发出了令牌,还是机器 B 发出了。

    【讨论】:

    • 我已经为你澄清了我的最后一行。如果机器 .10 和 .11 具有相同的密钥,则它们的令牌是可互换的
    【解决方案3】:

    无处,令牌未保存在服务器中。在documentation你可以阅读

    身份验证:这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,从而允许用户访问该令牌允许的路由、服务和资源。

    你必须明白:

    • 当您收到登录请求时,将令牌返回给用户(如果请求有效)
    • 在每次请求时,客户端都会将令牌发回给您,您将能够验证此令牌是否与您发送的令牌相对应。大多数情况下,令牌将在请求标头中提供,因此在服务器端您将能够使用req.headers[<token_property_here>] 访问它

    然后要验证,你需要运行这种代码

    jwt.verify(req.headers['x-auth-token'], 'secret', function (err, res) {
        if(err){
            return res.json({result: 'failure'});
        }
        // Else do something else
    }
    

    【讨论】:

      【解决方案4】:

      使用 jwt,您可以将令牌保存在客户端上。通常在 localStorage 或 sessionStorage 上,然后每次在授权标头中发出请求时发送令牌。
      或者像stormpath 推荐的方式一样,将 jwt 保存在带有 httpOnly 和安全标志 的 cookie 上(阅读说明)。
      因此,每次您的用户需要访问某个资源时,您都需要检查 cookie。
      在创建 jwt 时,您可以将其保存到 cookie 中:

      res.cookie('token', jwt, { httpOnly: true, secure: true });
      

      然后您可以创建一个验证身份验证的中间件。

      const UserAuthenticated = (req, res, next) => {
      
              const token = req.cookies.token; //if cookie not exist, user is not authenticated (httpOnly flag)    
      
              jwt.verify(token_sent_by_used, 'secret', function (err, res) {
                      if (!err) {
                          req.token = res.validToken;
                          next();
                      } else {
                          res.send('Not authenticated');
                      }
              });
      };
      
      //In your endpoint you use like:<br/>
      router.get('/someEndPoint', userAuthenticated, (req, res) => {
            // use the token here.
            const token = req.token;
          ...
      });
      

      然后,当在客户端发出请求时,不要忘记添加 withCredentials 以允许浏览器发送 cookie。

       superagent.post(url)
          .withCredentials()            
          .send(_msg);
      

      这就是你所需要的。

      【讨论】:

        猜你喜欢
        • 2020-05-11
        • 2013-11-16
        • 2012-03-09
        • 2012-07-07
        • 2011-10-29
        • 2017-03-09
        • 2015-06-06
        • 1970-01-01
        • 2010-12-20
        相关资源
        最近更新 更多