繁体   English   中英

使用此 JWT 库检查令牌是否过期

[英]Check if token expired using this JWT library

我已经像这样配置了令牌:

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

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

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

问题是这部分:

if (exp < (new Date().getTime() + 1) / 1000) {
  return false;
}

新日期().getTime() + 1) / 1000 = 1531335468.113

exp = 1531334595

因为不知道 JWT 使用什么时间格式...

我该如何解决这个问题?

这是答案:

if (Date.now() >= exp * 1000) {
  return false;
}

您应该使用jwt.verify 它将检查令牌是否过期。

如果源不受信任,则不应使用jwt.decode ,因为它不检查令牌是否有效。

没有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
}

或者更简单

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

或单线:

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

节点.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
}

或单线:

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

如果过期, verify本身会返回错误。 正如加百列所说,这样比较安全。

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

可悲的是, 安德烈斯蒙托亚的答案有一个缺陷,这与他如何比较对象有关。

我在这里找到了一个应该解决这个问题的解决方案:

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

感谢用户thejohnfreeman

以下函数无需任何库即可工作:

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

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

这适用于React Native ,但登录适用于所有类型。

isTokenExpired = async () => {
    try {
        const LoginTokenValue = await AsyncStorage.getItem('LoginTokenValue');
        if (JSON.parse(LoginTokenValue).RememberMe) {
            const { exp } = JwtDecode(LoginTokenValue);
            if (exp < (new Date().getTime() + 1) / 1000) {
                this.handleSetTimeout();
                return false;
            } else {
                //Navigate inside the application
                return true;
            }
        } else {
            //Navigate to the login page
        }
    } catch (err) {
        console.log('Spalsh -> isTokenExpired -> err', err);
        //Navigate to the login page
        return false;
    }
}

您可以使用jwt verify 方法来检查令牌的有效性。 err表示令牌已过期并将引发错误,因此您可以删除存储的令牌。

 jwt.verify(token, SECRET, (err, decoded) => {
      if (err) {
          localStorage.clear();
      }}
  });

有些答案省略了超级危险的验证步骤!

安全更换jwt.verify并进行以下更改

  • 不会在令牌过期时抛出,但会抛出无效令牌。
  • 返回 object 是{payload, expired}而不是payload

js版本

export function verifyJWT(token) {
  try {
    return { payload: jwt.verify(token, publicKey), expired: false };
  } catch (error) {
    if (error.name == "TokenExpiredError") {
      return { payload: jwt.decode(token), expired: true };
    }
    throw error;
  }
}

ts版本

export function verifyJWT(token: string) {
  try {
    return { payload: jwt.verify(token, publicKey), expired: false };
  } catch (error) {
    if ((error as Error).name == "TokenExpiredError") {
      return { payload: jwt.decode(token), expired: true };
    }
    throw error;
  }
}

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

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

// Pass in function expiration date to check token 
function checkToken(exp) {
    if (Date.now() <= exp * 1000) {
      console.log(true, 'token is not expired')
    } else { 
      console.log(false, 'token is expired') 
    }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM