我在这里检查了所有类似的问题,但是没有一个我需要的。 我在我的应用程序中确保了溃败,并向每个请求发送JWT,在这里一切都很好。 问题是JWT何时到期,而不是注销用户,我需要知道如何刷新该令牌并保持用户登录。
每个人都在谈论创建一种处理该问题的“中间件”,但是没有人说如何创建该中间件以及其中的内容?
那么,这样做的最佳实践是什么?我应该在发送任何请求之前检查JWT的到期日期吗?还是应该等待“ 401”响应,然后尝试刷新令牌(我不知道该怎么做),或者究竟是什么?
如果有人在Github上有这样的中间件,软件包或项目的工作示例可以帮助我解决这个问题,那就太好了。
我只对流程的前端部分感兴趣,从响应中发送什么,我期望接收什么以及如何处理。
答案 0 :(得分:5)
如果您正在使用Axios(强烈建议使用),则可以在响应的interceptors中声明令牌刷新行为。这将适用于Axios发出的所有https请求。
过程类似于
这里是一个例子:
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)
})
},
)
答案 1 :(得分:0)
您的中间件应该看起来像这段代码(例如,您可以使用所需的任何内容)
/* 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);
};