如何在 React.js 应用程序中刷新 JWT 令牌?
Posted
技术标签:
【中文标题】如何在 React.js 应用程序中刷新 JWT 令牌?【英文标题】:How to refresh JWT tokens in React.js Application? 【发布时间】:2019-06-29 02:43:56 【问题描述】:我在这里检查了所有类似的问题,但没有一个是我需要的。 我正在保护我的应用程序中的路线,并在每个请求中发送 JWT,这里一切都很好。 问题是当 JWT 过期时,我需要知道如何刷新该令牌并保持用户登录,而不是注销用户。
每个人都在谈论创建一个“中间件”来处理这个问题,但没有人说如何创建那个中间件以及其中包含什么?
那么,这样做的最佳做法是什么?我应该在发送任何请求之前检查 JWT 的到期日期吗?还是我应该等待“401”响应然后尝试刷新令牌(我不知道该怎么做),或者究竟是什么?
如果有人在 Github 上有这样的中间件或包或项目的工作示例,可以帮助我解决这个问题,那就太好了。
我只对流程的前端部分感兴趣,从 react 发送什么,我应该期望接收什么以及如何处理它。
【问题讨论】:
也许这个答案会给你一些有用的信息:JWT-example 如果您希望令牌不过期,请设置可能的最长过期时间(在某些情况下,您可以使用 '0' 表示无限期 - 但我认为至少在 jsonwebtoken 中省略了这一点)并使用某个例程刷新它。要刷新令牌,您的 API 需要一个端点来接收有效的、未过期的 JWT,并返回具有新设置的过期时间的相同签名 JWT。 【参考方案1】:如果您使用的是 Axios(我强烈推荐),您可以在响应的 interceptors 中声明您的令牌刷新行为。这将适用于 Axios 发出的所有 https 请求。
这个过程是这样的
-
检查错误状态是否为 401
如果有有效的刷新令牌:使用它来获取访问令牌
如果没有有效的刷新令牌:注销用户并返回
使用新令牌再次重做请求。
这是一个例子:
axios.interceptors.response.use(
(response) =>
return response
,
(error) =>
return new Promise((resolve) =>
const originalRequest = error.config
const refreshToken = localStorage.get('refresh_token')
if (error.response && error.response.status === 401 && error.config && !error.config.__isRetryRequest && refreshToken)
originalRequest._retry = true
const response = fetch(api.refreshToken,
method: 'POST',
headers:
'Content-Type': 'application/json',
,
body: JSON.stringify(
refresh: refreshToken,
),
)
.then((res) => res.json())
.then((res) =>
localStorage.set(res.access, 'token')
return axios(originalRequest)
)
resolve(response)
return Promise.reject(error)
)
,
)
【讨论】:
我最终做了完全相同的事情,当然使用不同的代码,但使用 Axios 拦截器的相同想法。我接受了你的答案作为正确答案。 我不喜欢这种做法,因为它提倡使用过期令牌,除非进行 HTTP 调用。发送带有过期令牌的 API 请求是不必要的请求。我宁愿实现一个提供 getToken 方法的身份验证服务。每次调用该方法时,您都会检查令牌是否已过期。如果过期,刷新它并返回新的。如果没有,请从存储中退回。在您的请求拦截器中使用此方法,您可以在其中将令牌添加到标头。 在客户端保存刷新令牌是不安全的,是吗?【参考方案2】:你的 middelware 应该看起来像这个代码块(例如你可以使用任何你想要的东西)
/* eslint-disable */
import request from 'superagent';
function call(meta, token)
const method = meta.API_METHOD ? meta.API_METHOD : 'GET';
let req = request(method, 'http://localhost:8000/' + meta.API_CALL);
req = req.set( Authorization: `JWT $token` );
req = meta.API_TYPE ? req.type('Content-Type', meta.API_TYPE) : req.set('Content-Type', 'application/json');
if (meta.API_PAYLOAD)
req = req.send(meta.API_PAYLOAD);
if (meta.API_QUERY)
req.query(meta.API_QUERY);
return req;
export default store => next => action =>
const state = store.getState();
const token = state.logged && state.logged.get('token') ?
state.logged.get('token') : 'eyJhbGciOiJIUzUxMiJ9';
if (action.meta && action.meta.API_CALL)
call(action.meta, token)
.then((res) =>
store.dispatch(
type: action.meta.API_SUCCESS,
result: res.body,
);
)
.catch(( status, response ) =>
if (action.meta.API_ERRORS && action.meta.API_ERRORS[status])
return store.dispatch(
type: action.meta.API_ERRORS[status],
result: response.body,
);
if (action.meta.API_ERRORS && action.meta.API_ERRORS[status] === '401')
/*call the refresh token api*/
call(<Your Meta for refreshing>, <expiredtoken>)
.then((res) =>
store.dispatch(
type: action.meta.API_SUCCESS,
result: res.body,
);
)
.catch(( status, response ) =>
if (action.meta.API_ERRORS && action.meta.API_ERRORS[status])
return store.dispatch(
type: action.meta.API_ERRORS[status],
result: response.body,
);
throw response;
);
throw response;
);
return next(action);
;
【讨论】:
能否请您在 react.js 示例中使用该中间件?以上是关于如何在 React.js 应用程序中刷新 JWT 令牌?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Spring Boot jwt 将身份验证系统连接到 React.js