我正在处理一个包含许多API请求的React应用程序。该应用程序的结构是
登录时,我收到响应令牌,并将令牌保存在本地存储中以供其他API请求使用。
此令牌每30分钟过期一次,如果我在30分钟后发出API请求,则请求中的状态为401。我正在使用此401状态注销并清除本地存储中的令牌数据。
示例请求
export function stationDailyUsage(data) {
return dispatch => {
dispatch(dailyUsageLoading());
axios.get(`${API_URL}/Dashboard/DailyUsage?type=${data.type}&date=${data.date}`, {
headers: {
'Authorization': `Bearer ${token}`
},
})
.then(res => {
if (res.data.success === true) {
dispatch(dailyUsageSuccess(res.data));
} else {
console.log("error");
}
})
.catch(function (error) {
if(error.response.status === 401){
dispatch(logout());
}
});
}
}
所以要以这种方式注销,我必须对我使用的每个API(大约40个API)进行此检查。这是遵循的最佳方法还是有更好的方法来处理注销。我已经读过axios interceptors
,但不清楚如何在系统中实现它。任何帮助将不胜感激。
答案 0 :(得分:2)
将此代码放在项目的初始化或加载部分中,然后运行一次
那么每次您调用axios
时,此代码都会检查错误
在此处更改变量并使用
// Add a request interceptor
axios.interceptors.request.use((config) => {
let token = localStorage.getItem("token");
if (token) {
config.headers.credentials = 'include';
config.headers.Authorization = `Bearer ${token}`;
config.headers['Access-Control-Allow-Origin'] = '*';
config.headers['Content-Type'] = 'application/json';
}
return config;
}, (error) => {
alert('interceptor request has error');
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use((response) => {
return response;
}, (error) => {
if (error.response && error.response.data && error.response.data.error &&
(error.response.data.session === false || error.response.data.session === "false")) {
localStorage.removeItem("userId"); // <-- add your var
window.location = "/"; // <-- add your path
}
else if (error.response && error.response.data && error.response.data.error && error.response.data.error.message) {
toastMessage(error.response.data.error.message, 1);
}
else
if (error.response && error.response.status === 401) {
localStorage.removeItem("userId"); // <-- add your var
window.location = "/"; // <-- add your path
} else
return Promise.reject(error);
});
答案 1 :(得分:0)
您可以为axios
编写自己的包装,它应该是这样的:
import axios from 'axios';
const request = axios.create({
baseURL: backUrl,
timeout: 5000,
});
export const get = url => {
const expiresIn = localStorage.getItem('expiresIn');
const accessToken = localStorage.getItem('accessToken');
if (expiresIn && Date.now() > expiresIn) {
const refreshToken = localStorage.getItem('refreshToken');
request
.post('/oauth/token', {
grant_type: 'refresh_token',
refresh_token: refreshToken,
})
.then(res => {
store.dispatch(
loginSubmitted(
res.data.access_token,
res.data.refresh_token,
res.data.expires_in,
),
);
localStorage.setItem('accessToken', res.data.access_token);
localStorage.setItem('refreshToken', res.data.refresh_token);
localStorage.setItem('expiresIn', res.data.expires_in);
return request.get(url, {
headers: { Authorization: `bearer ${res.data.access_token}` },
accessToken: res.data.access_token,
});
})
.catch(err => {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('expiresIn');
});
}
return request.get(url, {
headers: { Authorization: `bearer ${accessToken}` },
accessToken,
});
};
因此它将在每个请求之前检查exprire_date
并发送新请求以获取新令牌,以使用户不会注销
答案 2 :(得分:0)
是的,如果您不能使用刷新令牌(应该给予刷新令牌以理想地保持登录状态),则部分正确。
使用axios拦截器拦截响应,直到它变成需要处理的错误(如401)。
axios.interceptors.response.use(function (response) {
// 200 type responses, this should be left as it is
return response;
}, function (error) {
// Handle your 401 error, maybe the UI changes and removing from local storage
return Promise.reject(error);
});