步骤如下:
1-token过期根据refresh_token获取新的token 重新获取数据
2-创建一个新的axios实例 【使用request防止再次进入请求拦截和请求响应而进入死循环】
3-根据请求相应的响应值 是不是401 是:说明token过期
然后进行判断store中的 user :{token:'*',refresh_token:'**'}中的 refresh_token和user对象是否存在 ,如果不存在说明之前没有登录过,直接去登录
4-使用新创建的axios 实例对象 requestFreshToken 发送新的请求 headers中的口令携带的是 refresh_token
5-获取token之后 将值重新赋值给user中的token
6-将user重新存入store中
7-重新获取刚才因为token失效而没有获取的数据 直接使用request 参数 来自error对象中【这里保存了之前token失效的请求数据】
具体实现 代码如下:
import axios from "axios";
import store from "@/store";
import router from "@/router";
import jsonBig from "json-bigint";
import { Toast } from "vant";
// var json = '{ "value" : 9223372036854775807, "v2": 123 }'
// // console.log(JSON.parse(json),777888);
// console.log(jsonBig.parse(json).value.toString(),88888);
const request = axios.create({
// 所有相应的数据就不会存在大数字问题了
transformResponse: [
function(data) {
try {
// 如果转换成功则返回转换的数据结果
return jsonBig.parse(data);
} catch (err) {
// 如果转换失败,则包装为统一数据格式并返回
return {
data
};
}
}
]
//baseURL: "http://toutiao-app.itheima.net"
});
// 创建一个新的axios实例对象 这样做的目的就是 不会进入之前的请求拦截和响应 防止进入死循环
const requestFreshToken = axios.create();
// 添加请求拦截器
request.interceptors.request.use(
function(config) {
// 在发送请求之前做些什么
//console.log(config, 9999);
// if (window.localStorage.getItem('SET_TOKEN')) {
// config.headers.Authorization = 'Bearer ' + JSON.parse(window.localStorage.getItem('SET_TOKEN')).token
// }
if (store.state.user) {
config.headers.Authorization = "Bearer " + store.state.user.token;
}
return config;
},
function(error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
request.interceptors.response.use(
function(response) {
console.log(response, 3);
return response;
},
async function(error) {
console.log(error.response, 222);
// 对响应错误做点什么
// 对响应数据做点什么
const status = error.response.status;
if (status == 400) {
// 请求参数错误
Toast.file("请求参数错误");
} else if (status == 401) {
// 用户认证失败 若传递token,但token过期,则返回401
/*
token过期 根据refresh-token获取新的token
1-发送请求 获取新的token
2-根据新的token重新发送请求 实现无感刷新
*/
const { user } = store.state;
if (!user || !user.refresh_token) {
// 完全没有登陆过 无token
return router.push("/login");
}
// 有token 但是 token过期
try {
// 根据 refresh_token 获取新的token
const { data } = await requestFreshToken({
method: "PUT",
url: "/v1_0/authorizations",
headers: {
Authorization: "Bearer " + user.refresh_token
}
});
// 重新对user中token进行赋值
user.token = data.data.token;
// 将新的user对象重新存到store中
store.commit("setUser", user);
// 这里重新发送请求后 使用的是request 又会走上面的请求拦截 又会重新携带刚刚存的新的token
return request(error.response.config);
} catch (error) {}
// 捕获异常就直接重新登陆
return router.push("/login");
Toast.file("用户认证失败");
} else if (status == 403) {
// 客户端没有权限
Toast.file("客户端没有权限");
} else if (status == 405) {
// 请求方法不支持
Toast.file("请求方法不支持");
}
return Promise.reject(error);
}
);
export default request;