在日常开发过程中,我们经常需要处理 Token 过期的情况,以前的处理方式通常是后端在返回 Token 时一并返回一个过期时间,前端保存此过期时间,在之后的交互中以此判断该 Token 是否已过期。
由于我之前只做前端开发,并没有深入去了解 Token 的相关知识,直到开始接触后端开发后才发现,Token 本身就可以携带过期时间。
在 JWT Handbook 中讲到了两个字段 exp
和 iat
,分别对应 Token 的过期时间和生成时间,两者的单位都是秒,Handbook 中对两者的解释如下:
- exp: from the word expiration (time). A number representing a specific date and time in the format “seconds since epoch” as defined by POSIX6 . This claims sets the exact moment from which this JWT is considered invalid. Some implementations may allow for a certain skew between clocks (by considering this JWT to be valid for a few minutes after the expiration date).
- iat: from issued at (time). A number representing a specific date and time (in the same format as exp and nbf) at which this JWT was issued.
因此,仅通过 exp
这个字段,我们就可以直接从 Token 本身进行过期判断,而不需要额外的信息。
示例
后端在生成 Token 时指定过期时间:
const jwt = require('jsonwebtoken');
const token = jwt.sign({uid: "abcdf123", isVip: false, username: "Jack"}, {
expiresIn: `30d`,
algorithm: "RS512"
});
在前端我们可以使用 jwt-decode
来对 Token 进行解码:
import jwt_decode from "jwt-decode";
const decoded = jwt_decode(token);
console.log(decoded);
得到的解码信息如下:
/*{
uid: "abcdf123",
username: "Jack",
isVip: false,
exp: 1393286893,
iat: 1393268893
}*/
将 exp
的值乘以 1000 以转换成毫秒数,与当前时间的毫秒数做对比,即可判断 Token 是否过期:
if (decoded.exp * 1000 < Date.now()) {
console.log("token expired!")
} else {
console.log("token not expired!")
}
虽然 exp
的单位为秒,换算为毫秒后精度上会有一点损失,但这点损失算不上问题。
结语
相比额外存储过期时间,显然直接从 Token 本身进行判断更加安全。