【问题标题】:Unable to set Exp and Iat for JWT correctly无法为 JWT 正确设置 Exp 和 Iat
【发布时间】:2016-01-24 04:11:24
【问题描述】:

我有点被这个难住了。我正在尝试设置一个有效的 JWT。我正在使用带有 jsonwebtoken 中间件的 node.js。我遵循了位于 repo (located here) 上的文档,但我一直得到错误的 Exp 和 Iat。显然我想把这件事做对,这样我就不允许 JWT 过期了。

作为测试,我有以下代码:

var token = jwt.sign({"id": user._id}, configGeneral.JWT, { expiresIn: '1h' });

var decoded = jwt.decode(token, configGeneral.JWT);

var d1 = new Date(decoded.exp);
var d2 = new Date(decoded.iat);

console.log(decoded);
console.log(d1);
console.log(d2);

这个的输出是:

{ id: '56253091fe0397c80133f3e4',
  iat: 1445714161,
  exp: 1445717761 }
Sat Jan 17 1970 19:35:17 GMT+0200 (South Africa Standard Time)
Sat Jan 17 1970 19:35:14 GMT+0200 (South Africa Standard Time)

如何让时间戳不反映 javascript 纪元,而是反映 1 小时后的时间? (对于 iat 和 exp。)

【问题讨论】:

    标签: javascript node.js jwt json-web-token


    【解决方案1】:

    通过将*1000 添加到expiat,您将看到正确的日期。

    var d1 = new Date(decoded.exp*1000);
    var d2 = new Date(decoded.iat*1000);

    【讨论】:

      【解决方案2】:

      库创建的纪元是 Unix 纪元时间,您可以在任何网站 (like this for example) 中查看 jwt iat 和 exp 值 & 您会发现它们有效

      例如,您的问题 1445714161 中的 iat 是 格林威治标准时间:2015 年 10 月 24 日星期六 19:16:01

      您的 exp 是 1445717761,即 GMT:2015 年 10 月 24 日星期六 20:16:01

      所以从一开始你的目标就是 1 小时后

      如果你尝试使用 javascript new Date(1445714161) 你会得到一个错误的时间

      因此,根据 jsonwebtoken 库 here 的文档创建 iat(自动创建)和 exp 声明的最简单方法

      您可以通过这种方式轻松设置到期时间

      jwt.sign({
        data: 'foobar'
      }, 'secret', { expiresIn: 60 * 60 });
      

      甚至更好:

      jwt.sign({
        data: 'foobar'
      }, 'secret', { expiresIn: '1h' });
      

      这会将 exp 声明放入 jwt 中,如下所示,iat 和 exp 都具有正确的 unix 纪元时间(到期时间比发出时间晚 1 小时),因此例如它将是这样的(可以是在 jwt 库中轻松验证):

      {
        "data": "foobar",
        "iat": 1539549664,
        "exp": 1539553264
      }
      

      请注意,上面的 expiresIn 选项是特定于 jsonwebtoken 库的,更通用的方式如下:

      jwt.sign({
        exp: Math.floor(Date.now() / 1000) + (60 * 60),
        data: 'foobar'
      }, 'secret');
      

      【讨论】:

        【解决方案3】:

        根据 Krzysztof Sztompka 发布的内容,我可以让分机显示正确的到期日期。 (我原来的要求是未来1小时)

        为了跟踪更改与以前的错误,我不会更新上面的代码,所以这是我所做的更改:

        var d = new Date();
        
        var calculatedExpiresIn = (((d.getTime()) + (60 * 60 * 1000)) - (d.getTime() - d.getMilliseconds()) / 1000);
        
        var token = jwt.sign({"id": user._id}, configGeneral.JWT, { expiresIn: calculatedExpiresIn });
        

        console.log 现在将显示 Ext 是我想要的,现在 + 1 小时。

        为了让 Iat 显示正确的日期(在 sign 函数中设置它,然后在 decode 函数中对其进行健全检查之后),我必须将它设置为有效负载的一部分。我得到了答案here

        所以最后为了让 Iat 正确显示,我将它添加到有效负载中,如下所示:

        var token = jwt.sign({"id": user._id, "iat": (new Date().getTime())}, configGeneral.JWT, { expiresIn: calculatedExpiresIn });
        

        这给出了以下输出:

        { id: '56253091fe0397c80133f3e4',
          iat: 1445763099706,
          exp: 1445766699705 }
        Sun Oct 25 2015 11:51:39 GMT+0200 (South Africa Standard Time)
        Sun Oct 25 2015 10:51:39 GMT+0200 (South Africa Standard Time)
        

        这是未编码的 JWT,我将在用户成功登录后将其传回给用户,并允许我检查他们必须传递的 JWT,因为未来的每个请求仍然有效且尚未过期。

        【讨论】:

          【解决方案4】:

          这个:

          new Date().getTime()
          

          给你以毫秒为单位的时间。但是 jwt 令牌 (iat, exp) 中的时间是以秒为单位的,因此我们必须将结果除以 1000。

          var actualTimeInSeconds = new Date().getTime()/1000;
          

          如何从现在开始以秒为单位获得一些时间:

          (new Date().getTime() + someTimeInSeconds * 1000)/1000
          

          如果您需要 1 小时后:

          (new Date().getTime() + 60 * 60 * 1000)/1000
          

          因为 1h = 60min * 60 s

          此时您从 jwt 令牌中获得了以秒为单位的时间,并以秒为单位计算了时间。您应该只比较这些值。

          正是在您的情况下,您应该将 jwt 令牌时间与您的实际时间(以秒为单位)进行比较。如果 jwt 令牌过期时间大于实际时间,则表示它仍然有效。 来自 jwt 令牌的文档:

          处理 exp 声明要求当前日期/时间必须早于 exp 声明中列出的到期日期/时间。

          编辑:

          要从 iat 获取 coorect 日期,请将值乘以 1000 并添加到新的 Date 构造函数:

          new Date(iat*1000)
          

          【讨论】:

          • 如果我将您的第 4 个代码示例输入 expiresIn 中,我会得到一个时代加上几天(1970 年 2 月 3 日)。但是,如果我将除以 1000 去除,我会得到今天的日期 + 时代的 17 天和几个小时。我玩了一下,但让分机显示正确的到期日期(请参阅我的问题更新)。但是,这仍然给我留下了不正确的 Iat。
          • 我发布了我想出的解决方案,因为它实际上解决了我没有将 Ext 和 Iat 正确放入 JWT 的问题。我可能没有很好地解释那部分,我认为您可能因此误解了该要求。但是,您的输入绝对帮助我找到了正确的答案,谢谢! :) 你说得对,我必须解码 JWT,然后将 Ext 的秒数与我当前的时间进行比较,以确定 JWT 是否已过期。
          • 我更喜欢new Date().getTime()/1000 + 60 * 60
          猜你喜欢
          • 2023-03-21
          • 2017-03-29
          • 2015-11-12
          • 1970-01-01
          • 2012-06-05
          • 2012-05-19
          • 1970-01-01
          • 2018-05-24
          • 1970-01-01
          相关资源
          最近更新 更多