javascript 无法为 JWT 正确设置 Exp 和 Iat

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33322407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 16:21:31  来源:igfitidea点击:

Unable to set Exp and Iat for JWT correctly

javascriptnode.jsjwtjson-web-token

提问by Ebbs

I am a bit stumped by this one. I am trying to set up a valid JWT. I am using node.js with the jsonwebtoken middleware. I have followed the documentation located on the repo (located here), but I keep getting the wrong Exp and Iat. Obviously I would like to get this right so that I don't allow JWT's which has expired.

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

As a test I have the following code:

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

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);

The output of this is:

这个的输出是:

{ 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)

How do I get the timestamp to not reflect the javascript epoch, but rather the time 1 hour from now? (for both the iat and exp.)

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

采纳答案by Ebbs

Based on what Krzysztof Sztompka posted, I could get the Ext to show the correct expiry date. (my original requirement was for 1 hour in the future)

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

To keep track of the change vs previous mistakes, I won't update the code above, so here is what I changed:

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

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 });

The console.log's will now show that the Ext is as I wanted it, now + 1 hour.

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

To get the Iat to show the correct date (after setting it in the signfunction and then sanity checking it in the decodefunction), I had to set it as part of the payload. I got my answer here

为了让 Iat 显示正确的日期(在sign函数中设置它然后在decode函数中检查它的完整性之后),我必须将它设置为有效负载的一部分。我在这里得到了答案

So finally to get the Iat to show correctly I added it to the payload as shown here:

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

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

This gives an output of:

这给出了以下输出:

{ 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)

This is the unencoded JWT which I will passed back to the users when they have signed in successfully and will allow me to check whether the JWT they have to pass as every future request is still valid and hasn't expired yet.

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

回答by Krzysztof Sztompka

This:

这:

new Date().getTime()

give you time in miliseconds. But time in jwt token (iat, exp) is in seconds, therefore we have to divide result by 1000.

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

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

How to get some time in seconds from now:

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

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

If you need 1 hour from now:

如果您需要 1 小时后:

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

because 1h = 60min * 60 s

因为 1h = 60min * 60 s

And at this moment you have time in seconds from jwt token and calculated time in seconds. You should only compare this values.

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

Precisely in your situation you should compare jwt token time with your actual time in seconds. If jwt token expiration time is greater then actual time it means that it is still valid.From docs of jwt token:

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

The processing of the exp claim requires that the current date/time MUST be before the expiration date/time listed in the exp claim.

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

Edit:

编辑:

To get coorect date from iat, multiply value by 1000 and add to new Date constructor:

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

new Date(iat*1000)

回答by Ahmed Elkoussy

The epoch created by the library is Unix epoch time & you can check the jwt iat & exp values in any website (like this for example) & you will find them valid

该库创建的纪元是 Unix 纪元时间,您可以在任何网站上检查 jwt iat 和 exp 值(例如这样),您会发现它们是有效的

For example, the iat in your question 1445714161 is GMT: Saturday, 24 October 2015 19:16:01

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

You exp was 1445717761 which is GMT: Saturday, 24 October 2015 20:16:01

您的 exp 为 1445717761,即格林威治标准时间:2015 年 10 月 24 日星期六 20:16:01

So it was 1 hour later which was your objective from the beginning

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

if you try in javascript new Date(1445714161) you will get a wrong time

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

So the easiest way to create the iat (created automatically) & exp claims as per the documentation of the jsonwebtoken library here

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

You can set the expiry easily this way

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

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

or even better:

甚至更好:

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

This will put the exp claim in the jwt as follows, with the correct unix epoch time for both iat & exp (with expiry 1 hour later than issued at time), so for example it will be like this (which can be verified easily in jwt libraries):

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

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

Note that the above expiresInoption is specific for jsonwebtoken library & a more generic way will be like this:

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

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

回答by Yahia Badr

By adding *1000to the expand iat, you will see the right dates.

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

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

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