做项目时遇到的一个头疼的问题,也是首次接触,只能自己摸索,
在网上查了好多资料,有的都是写了重要步骤,没有完整的代码,所以花了我一周的时间去弄这个问题,也查找了很多资料,然后深入学习axios;
1.定时刷新token,简而言之就是隔一段时间去刷新一次token,当然前提是原来的token还没有过期的情况下,才能去刷新,否则直接跳回登录首页;
import axios from 'axios'; // 引入axios
// 创建实例时设置配置的默认值
// 注意这个实例 在之后的api请求接口时全部用的是server
let service = axios.create({
baseURL: 'http://xxxxx
});
// 是否正在刷新的标志
window.isRefreshing = false;
// 存储请求的数组
let refreshSubscribers = [];
/*将所有的请求都push到数组中*/
function subscribeTokenRefresh(cb) {
refreshSubscribers.push(cb);
}
// 数组中的请求得到新的token之后自执行,用新的token去请求数据
function onRrefreshed(token) {
refreshSubscribers.map(cb => cb(token));
}
// 刷新token的过期时间判断
function isRefreshTokenExpired() {
let oData = loadTimeStamp(); // 这是在登陆时候保存的时间戳
let nDta = new Date().getTime();
let stamp = nDta - oData;
let minutes = parseInt((stamp % (1000 * 60 * 60)) / (1000 * 60));
return minutes >= 30? true : false;
}
刷新token
function getRefreshToken() { // 刷新token 注意这里用到的service
return service.post(proApi.api.refreshUserTokenApi)
.then((res) => {
return Promise.resolve(res.data)
})
}
axios 拦截器,主要实在请求时判断token是否即将过期,然后请求刷新token
/*请求拦截器*/
service.interceptors.request.use(
config => {
const authTk = loadUserToken(); // 本地保存的token
/*判断token是否存在*/
if (authTk) {
/*在请求头中添加token类型、token*/
config.headers.Authorization = loadUserKey() + ' ' + loadUserToken();
config.url =config.url+'?t='+(new Date()).getTime().toString(); // 清楚缓存
/*判断token是否将要过期 */
if (isRefreshTokenExpired() && (config.url.indexOf('user/refresh') === -1 || config.url.indexOf('bidder/refresh') === -1)) {
if (!window.isRefreshing) { // /*判断是否正在刷新*/
window.isRefreshing = true;
/*发起刷新token的请求*/
getRefreshToken().then(res => {
window.isRefreshing = false;
saveUserToken(res.access_token);
saveUserKey(res.token_type);
saveTimeStamp(new Date().getTime());
/*执行数组里的函数,重新发起被挂起的请求*/
config.headers.Authorization = res.token_type + ' ' + res.token;
onRrefreshed(res.access_token);
/*执行onRefreshed函数后清空数组中保存的请求*/
refreshSubscribers = []
}).catch(err => {
/*清除本地保存的*/
clearAllCache();
window.location.href = '#/user/login'
});
/*把请求(token)=>{....}都push到一个数组中*/
let retry = new Promise((resolve, reject) => {
/*(token) => {...}这个函数就是回调函数*/
subscribeTokenRefresh((token) => {
// config.headers.common['Authorization'] = 'bearer ' + token;
config.headers.Authorization = 'bearer ' + token;
/*将请求挂起*/
resolve(config)
})
});
return retry
}
return config
} else {
return config
}
} else {
return config
}
},
/*错误操作*/
err => {
return Promise.reject(err)
}
);
axios拦截器response对过期token拦截,然后跳转登录界面
service.interceptors.response.use(response=>{
return response;
},
error => {
let errorResponse = error.response;
if (errorResponse.status === 401) {
Message.error('token已过期,请重新登录'); // Message是element-ui的一个组件
window.location.href = '#/login';
clearAllCache(); // 清空所有缓存
}
return Promise.reject(error);
});
export default service;
在以上实例化axios之后,在其他api请求的时候,使用的形式如下
import service from '@/assets/js/axios.config';
service.post(proApi.api.getListApi, data)
.then((res) => {
if (res.data.code == ERR_OK) { // ERR_OK 是自己设置的统一错误代码
return Promise.resolve(res.data)
}
})
热门评论
第一次的token获取没有快过期的token进行比较,如何去获取呢?