如何在 React 上检测 jwt 令牌过期

Posted

技术标签:

【中文标题】如何在 React 上检测 jwt 令牌过期【英文标题】:How to detect jwt token expire on React 【发布时间】:2021-03-19 11:06:12 【问题描述】:

使用后端 node.js,我创建了一个具有过期时间的 JWT 令牌:

signToken = (user) => 
    return jwt.sign( id: user.userId , process.env.JWT_SECRET,  expiresIn: 60 * 60 * 24 * 10 ) // 1h = 60 * 60

使用前端的 React 应用程序,当用户登录时,我会将这个 JWT 令牌与返回数据一起传递并保存到本地存储(我正在使用 Redux):

const result = await userLogin( username, password )
dispatch( type: USER_LOGIN_SUCCESS, payload: result.data.data )
const  userReducer  = getState()
window.localStorage.setItem("accessToken", JSON.stringify(userReducer.token))

每个 api 都需要此令牌进行授权,我将在标头中传递此令牌。我在 axios 请求拦截器中设置:

instance.interceptors.request.use(
    (config) => 
        const accessToken = localStorage.getItem("accessToken")
        config.headers.Authorization = accessToken ? `Bearer $accessToken` : ""
        if (config.url.includes("/files/")) 
            config.headers["Content-Type"] = "multipart/form-data"
        
        return config
    ,
    (error) => 
        return Promise.reject(error.response)
    
)

我的问题是如何检测令牌是否在 React 上过期。在这个 React 应用中,我使用的是 axios、redux、react-redux 和 react router。

【问题讨论】:

如果令牌无效,您的 API 会返回一个错误,您能不能只使用该错误作为您需要新令牌的指示? 一种方法是在localStorage 中添加令牌到期时间戳以及令牌。当令牌即将到期时,您可以执行必要的操作,例如令牌重新生成、验证等 【参考方案1】:

可以补充给出的答案是,假设您将 jwt 令牌设置为从现在开始持续 10 天,您将执行以下操作:10 * 24 * 60 * 60 * 1000 所以这将以毫秒为单位设置从现在开始的 10 天。

现在,当您在服务器中收到以毫秒为单位的过期令牌时,您现在要做的是,不要等待收到错误消息,但您要做的是 比较 如果令牌中的日期(在毫秒)大于当前日期,那么如果这是真的,那么你知道令牌仍然有效......

替代方案

由于您已经将 Jwt 存储在 localStorage 中,因此您可以切换到存储在 Cookie 中确实没有什么区别,但从某种意义上说,一旦令牌过期,它将从您的 cookie 存储中删除,从而使服务器验证变得容易,即如果 cookie未发送意味着它已经过期,但这仅适用于存储在 cookie 中

【讨论】:

【参考方案2】:

我同意 Cory 的评论,即您应该在服务器而不是客户端上进行验证。如果您想做一些基本检查,假设您的 JWT 正文未加密,以下将起作用。

// Some fake JWT I made using an online builder
const exampleJWT = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MDc0MDc3NTYsImV4cCI6MTYzODk0Mzc1NiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.cfBNHOIaUSAVtLHbxlOmMZtp-giA7-v8yJpMyGooefE`;

function getPayload(jwt)
  // A JWT has 3 parts separated by '.'
  // The middle part is a base64 encoded JSON
  // decode the base64 
  return atob(jwt.split(".")[1])


const payload = getPayload(exampleJWT);

const expiration = new Date(payload.exp);
const now = new Date();
const fiveMinutes = 1000 * 60 * 5;

if( expiration.getTime() - now.getTime() < fiveMinutes )
  console.log("JWT has expired or will expire soon");
 else 
  console.log("JWT is valid for more than 5 minutes", payload);

【讨论】:

是的,已经有服务器端验证。我有一个中间件检测令牌是否在每个 api 端点之前工作。所以从你的意思来看,我不需要 clinet 端令牌过期检查?

以上是关于如何在 React 上检测 jwt 令牌过期的主要内容,如果未能解决你的问题,请参考以下文章

如何在 react native 和 redux 应用程序中处理 JWT 令牌到期

如何在 React.js 应用程序中刷新 JWT 令牌?

当 jwt 刷新令牌未过期时,React Native 应用程序注销

如何在jwt中过期时刷新令牌

我如何在 jwt 令牌中设置过期 30 分钟

python jwt中令牌过期时如何提取jwt令牌有效负载