如果存储在本地存储中,检查 jwt 令牌过期状态的最佳方法
Best way to check jwt token expire status if stored in localstorage
我想检查客户端的令牌是否过期。
我的令牌存储在本地存储中。
现在我要做的是:调用服务器以检查它是否有效,但我只在路径为: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
我想使用套接字,但我不知道它是否可行。
想法是:客户端保持监听状态,只要令牌过期,服务器就会发出消息。
知道我该怎么做吗?
您可以使用一个库(如 jwt_decode)来解码您的 JWT 令牌,其中它很可能包含一个您可以检查的过期时间戳(将它与此时的当前时间戳进行比较)以及它是否超出(过期)只需将其从本地存储中删除并将用户重定向到登录页面。
但是你还必须考虑为调用你的 API 的函数添加一个 catch
块来检查任何 401
响应状态代码也做同样的事情(以防令牌是有效的,而用户正在移动它的到期日期结束)
有不同的技术。
请注意,在两台不同机器上处理时间(在本例中为过期时间)可能会由于时间抖动或时钟未对准而导致问题,因此不是那么简单
被动过期
我最喜欢的模式是有一个专用的服务器错误。
当令牌过期时,您的服务器应该响应一个特定的错误(由于角色访问而与 401 Unauthorized
区分开来)。然后,您向客户端添加一个 HTTP 中间件:
- 检测到这个错误响应
- 删除本地令牌并导航到
/auth/login
或者如果你有 renew token
:
- 检测到这个错误响应
- 尝试续订
JWT
- 成功时重复原始请求,失败时导航到授权页面。
这是一个被动系统,可让您将 JWT
视为晦涩的字符串,并且不存在与时间相关的问题。
Return一个单独的字段
如果出于安全原因,即使 用户未与 UI 交互(就像银行网站那样),您希望在会话过期时隐藏敏感信息) 您需要知道令牌何时过期。一种常见的技术是 return 过期时间和令牌(在身份验证响应中)。
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
"expiresAt": 1234567890
}
甚至更好
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
"expiresIn": 600
}
第一个 return 是相对于 服务器时间 的令牌过期的 UNIX 时间。这会受到时间抖动或时钟不对齐的影响(这可能会导致错误)。第二个 更好 [=79=] 因为它让 UI 知道令牌将在多少秒内(自收到响应后)过期,然后可以使用它来计算 UNIX根据当地时钟时间。
通常从 expiresAt
和 expiresIn
中删除一个小的时间步长以避免时钟抖动和时钟漂移问题。
解析 JWT
如果您没有其他解决方案,您可以随时解析 JWT
:
const JWT = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.1c_yQjnMZfKUb4UTDE_WvbC71f8xxtyMsdqKKkI1hF8`;
const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
console.log(jwtPayload.exp);
我想检查客户端的令牌是否过期。
我的令牌存储在本地存储中。
现在我要做的是:调用服务器以检查它是否有效,但我只在路径为: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
我想使用套接字,但我不知道它是否可行。
想法是:客户端保持监听状态,只要令牌过期,服务器就会发出消息。
知道我该怎么做吗?
您可以使用一个库(如 jwt_decode)来解码您的 JWT 令牌,其中它很可能包含一个您可以检查的过期时间戳(将它与此时的当前时间戳进行比较)以及它是否超出(过期)只需将其从本地存储中删除并将用户重定向到登录页面。
但是你还必须考虑为调用你的 API 的函数添加一个 catch
块来检查任何 401
响应状态代码也做同样的事情(以防令牌是有效的,而用户正在移动它的到期日期结束)
有不同的技术。
请注意,在两台不同机器上处理时间(在本例中为过期时间)可能会由于时间抖动或时钟未对准而导致问题,因此不是那么简单
被动过期
我最喜欢的模式是有一个专用的服务器错误。
当令牌过期时,您的服务器应该响应一个特定的错误(由于角色访问而与 401 Unauthorized
区分开来)。然后,您向客户端添加一个 HTTP 中间件:
- 检测到这个错误响应
- 删除本地令牌并导航到
/auth/login
或者如果你有 renew token
:
- 检测到这个错误响应
- 尝试续订
JWT
- 成功时重复原始请求,失败时导航到授权页面。
这是一个被动系统,可让您将 JWT
视为晦涩的字符串,并且不存在与时间相关的问题。
Return一个单独的字段
如果出于安全原因,即使 用户未与 UI 交互(就像银行网站那样),您希望在会话过期时隐藏敏感信息) 您需要知道令牌何时过期。一种常见的技术是 return 过期时间和令牌(在身份验证响应中)。
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
"expiresAt": 1234567890
}
甚至更好
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.JFDV4mOKKh0sMfkBKvsbvm8iWjHEGBXtPvC49ob3qiI",
"expiresIn": 600
}
第一个 return 是相对于 服务器时间 的令牌过期的 UNIX 时间。这会受到时间抖动或时钟不对齐的影响(这可能会导致错误)。第二个 更好 [=79=] 因为它让 UI 知道令牌将在多少秒内(自收到响应后)过期,然后可以使用它来计算 UNIX根据当地时钟时间。
通常从 expiresAt
和 expiresIn
中删除一个小的时间步长以避免时钟抖动和时钟漂移问题。
解析 JWT
如果您没有其他解决方案,您可以随时解析 JWT
:
const JWT = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyMzQ1Njc4OTAsIm5hbWUiOiJKb2huIERvZSIsImlhdCI6MTUxNjIzOTAyMn0.1c_yQjnMZfKUb4UTDE_WvbC71f8xxtyMsdqKKkI1hF8`;
const jwtPayload = JSON.parse(window.atob(JWT.split('.')[1]))
console.log(jwtPayload.exp);