如果存储在本地存储中,检查 jwt 令牌过期状态的最佳方法

Posted

技术标签:

【中文标题】如果存储在本地存储中,检查 jwt 令牌过期状态的最佳方法【英文标题】:Best way to check jwt token expire status if stored in localstorage 【发布时间】:2021-11-20 08:52:43 【问题描述】:

我想在客户端检查令牌是否过期。

我的令牌存储在本地存储中。

现在我要做的是:调用服务器以检查它是否有效,但我只在路径为:https:exp.com/

代码:

  useEffect(() => 
    verifyToken(auth.token).then((res) => 
      if (res.status !== 'success' && res.message === 'Token expired') 
        signoutClient(() => 
          router.push('/auth/login');
        );
      
    );
  , [auth.token, router]);

现在的问题是,如果用户直接转到另一个 url exp 怎么办:https:exp.com/helloworld

我正在考虑使用套接字,但我不知道它是否可以工作。

想法是:客户端保持监听状态,只要令牌过期,服务器就会发出一条消息。

知道我该怎么做吗?

【问题讨论】:

您不应该在客户端检查您的访问令牌。但是您仍然想要它,您可以将访问令牌保存在 cookie 中并为其设置过期时间。 LocalStorage 永不过期 @lamtacvu 我猜问题没有改变,不知何故我必须检查 cookie 是否过期? 你不能使用 JWTs TTL 作为跟踪有效性的一种方式吗? 【参考方案1】:

有不同的技术。

请注意,在两台不同的机器上处理时间(在这种情况下是过期)可能会由于时间抖动或时钟错位而导致问题,因此不是那么简单

被动过期

我最喜欢的模式是出现专用服务器错误。

您的服务器应在令牌过期时响应特定错误(由于角色访问权限而与401 Unauthorized 区分开来)。然后向客户端添加一个 HTTP 中间件:

检测到此错误响应 删除本地令牌并导航到/auth/login

或者如果你有renew token:

检测到此错误响应 尝试续订JWT 成功时重复原始请求或失败时导航到身份验证页面。

这是一个被动系统,允许您将JWT 视为一个晦涩的字符串,并且不存在与时间相关的问题。

返回一个单独的字段

如果出于安全原因,您希望在会话到期时隐藏敏感信息,即使用户没有与用户界面交互(如银行网站那样),您需要知道何时令牌将过期。一种常见的技术是将过期时间与令牌一起返回(在身份验证响应中)。


   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
   "expiresAt": 1234567890

甚至更好


   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
   "expiresIn": 600

第一个返回令牌到期相对于 服务器时间 的 UNIX 时间。这会受到时间抖动或时钟失调的影响(这可能会导致错误)。第二个更好,因为它让 UI 知道令牌将在多少秒内(因为收到响应)过期,然后可以用来根据本地时钟计算 UNIX 时间。

通常会从expiresAtexpiresIn 中删除一个小时间步,以避免时钟抖动和时钟漂移问题。

解析 JWT

如果没有其他解决方案,可以随时解析JWT

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

const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
console.log(jwtPayload.exp);

【讨论】:

【参考方案2】:

您可以使用 lib(如 jwt_decode)来解码您的 JWT 令牌,其中很可能包含您可以检查的过期时间戳(将其与当前时间戳进行比较)以及是否超过(过期)只需从本地存储中删除它并将用户重定向到登录页面。

但是您还必须考虑为调用您的 API 以检查任何 401 响应状态代码的函数添加一个 catch 块也执行相同操作(如果令牌有效,那么当用户四处走动时)它的有效期结束)

【讨论】:

那么你的意思是我必须检查每个页面上的令牌? 不,您可以在启动时检查一次,然后设置 catch 块以准备好以防401 返回

以上是关于如果存储在本地存储中,检查 jwt 令牌过期状态的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

jwt 访问令牌和刷新令牌流

如何在前端和后端存储 JWT 刷新令牌?

根据初始浏览器请求向服务器发送 JWT 令牌(使用本地存储)

其中 jsonwebtoken 存储在服务器 nodejs 中。用户注销后如何使 JWT 过期

BulletPHP 框架和 Firebase/JWT - 检查令牌错误

在永久存储中跟踪 JWT