jwt检查令牌是否过期

And*_*oya 17 node.js express jwt

我已经这样配置令牌:

jwt.sign(
  {
    user: pick(user, ['_id', 'username'])
  },
  secret,
  {
    expiresIn: '2m'
  }
);
Run Code Online (Sandbox Code Playgroud)

但是当我想检查令牌是否已过期时,此代码不起作用

function isAuthenticated() {
  const token = localStorage.getItem('token');
  const refreshToken = localStorage.getItem('refreshToken');
  try {
    decode(token);
    const { exp } = decode(refreshToken);
    if (exp < (new Date().getTime() + 1) / 1000) {
      return false;
    }
  } catch (err) {
    return false;
  }
  return true;
}
Run Code Online (Sandbox Code Playgroud)

问题是这部分:

if (exp < (new Date().getTime() + 1) / 1000) {
  return false;
}
Run Code Online (Sandbox Code Playgroud)

新的Date()。getTime()+1)/ 1000 = 1531335468.113

exp = 1531334595

因为我不知道JWT使用哪种时间格式...

我该如何解决?

谢谢!

Ema*_*uel 48

没有库的功能jwt

浏览器

function isTokenExpired(token) {
  const base64Url = token.split(".")[1];
  const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
  const jsonPayload = decodeURIComponent(
    atob(base64)
      .split("")
      .map(function (c) {
        return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
      })
      .join("")
  );

  const { exp } = JSON.parse(jsonPayload);
  const expired = Date.now() >= exp * 1000
  return expired
}
Run Code Online (Sandbox Code Playgroud)

或者更简单

function isTokenExpired(token) {
  const expiry = (JSON.parse(atob(token.split('.')[1]))).exp;
  return (Math.floor((new Date()).getTime() / 1000)) >= expiry;
}
Run Code Online (Sandbox Code Playgroud)

或者单行:

const isTokenExpired = token => Date.now() >= (JSON.parse(atob(token.split('.')[1]))).exp * 1000
Run Code Online (Sandbox Code Playgroud)

Node.js

function isTokenExpired(token) {
  const payloadBase64 = token.split('.')[1];
  const decodedJson = Buffer.from(payloadBase64, 'base64').toString();
  const decoded = JSON.parse(decodedJson)
  const exp = decoded.exp;
  const expired = (Date.now() >= exp * 1000)
  return expired
}
Run Code Online (Sandbox Code Playgroud)

或者单行:

const isTokenExpired = (token) => (Date.now() >= JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).exp * 1000)
Run Code Online (Sandbox Code Playgroud)

  • 很有意思!感谢你的分享 :)。 (3认同)

And*_*oya 32

如果有人想知道,这就是答案

if (Date.now() >= exp * 1000) {
  return false;
}
Run Code Online (Sandbox Code Playgroud)

  • @lony,它没有缺陷,Date.now()和JWT到期时间都标识自1970年1月1日00:00:00 UTC以来的时间。 (6认同)
  • 有缺陷,因为 now() 使用时区 (2认同)
  • 返回 false 是否意味着 token 已过期? (2认同)

Ras*_*mon 12

verify如果过期,本身会返回错误。正如@Gabriel 所说,更安全。

const jwt = require('jsonwebtoken')

router.use((req, res, next) => {
  const token = yourJwtService.getToken(req) // Get your token from the request
  jwt.verify(token, req.app.get('your-secret'), function(err, decoded) {
    if (err) throw new Error(err) // Manage different errors here (Expired, untrusted...)
    req.auth = decoded // If no error, token info is returned in 'decoded'
    next()
  });
})
Run Code Online (Sandbox Code Playgroud)

同样用async/await语法写成:

const jwt = require('jsonwebtoken')
const util = require('util');
const jwtVerifyAsync = util.promisify(jwt.verify);

router.use(async (req, res, next) => {
  const token = yourJwtService.getToken(req) // Get your token from the request
  try {
    req.auth = await jwtVerifyAsync(token, req.app.get('your-secret')) // If no error, token info is returned
  } catch (err) {
    throw new Error(err) // Manage different errors here (Expired, untrusted...)
  }
  next()
});
Run Code Online (Sandbox Code Playgroud)


Gab*_*leu 10

您应该使用jwt.verify,它将检查令牌是否已过期。 如果源不受信任,则不应使用jwt.decode,因为它不会检查令牌是否有效。

  • 哦,好的,但是您没有收到带有令牌的“expiresIn”? (2认同)

lon*_*ony 9

可悲的是@Andrés Montoya 的回答有一个缺陷,这与他比较 obj 的方式有关。我在这里找到了一个应该解决这个问题的解决方案:

const now = Date.now().valueOf() / 1000

if (typeof decoded.exp !== 'undefined' && decoded.exp < now) {
    throw new Error(`token expired: ${JSON.stringify(decoded)}`)
}
if (typeof decoded.nbf !== 'undefined' && decoded.nbf > now) {
    throw new Error(`token expired: ${JSON.stringify(decoded)}`)
}
Run Code Online (Sandbox Code Playgroud)

感谢约翰弗里曼!


San*_*dro 5

以下函数无需任何库即可运行:

function getJWTExpireDate(jwtToken: string) {
  if (jwtToken) {
    try {
      const [, payload] = jwtToken.split('.');
      const { exp: expires } = JSON.parse(window.atob(payload));
      if (typeof expires === 'number') {
        return new Date(expires * 1000);
      }
    } catch {
      // ignore
    }
  }
  return null;
}
Run Code Online (Sandbox Code Playgroud)

不要用它来检查令牌是否有效。一个很好的用例是在前端显示令牌何时过期。


Bam*_*ier 5

客户端

const JWT = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.1c_yQjnMZfKUb4UTDE_WvbC71f8xxtyMsdqKKkI1hF8";

const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
const isExpired = Date.now() >= jwtPayload.exp * 1000;

Run Code Online (Sandbox Code Playgroud)