axios 后台管理项目 - token刷新,拦截器设置
最近在公司做一个vue.js的后台管理系统。鉴于自己也是vue小白,在网上查阅了很多现成的资料,总算是把需求搞定了。
先来介绍一下需求:登录时请求token和refresh_token(用来刷新token),每一次请求后端接口的时候都要在header里带token,如果过期会报错401,在过期的半小时内用refresh_token重新请求可以刷新token,使用户不必被强制退出重新登录。
这个项目使用的axios和vue-router,解决方法如下:
参考:http://blog.csdn.net/qq673318522/article/details/55506650
思路
axios设置的思路是,先设置默认的数据,比如说超时时间,url前缀,然后设置request和response拦截器,request拦截器是在发送请求之前执行,response拦截器是在请求返回之后执行。
这里实现刷新token主要是在response拦截器做文章,请求返回401时先记录这次请求的设置config,然后请求刷新接口,刷新成功之后再重新发送一次之前失败的请求,因为config保存下来,所以发送请求的时候可以先把config中的token换成最新的token,再直接用axios(config),而不用担心其他的设置,从而实现重新请求。
那么问题在于如何知道刷新token成不成功呢,如果无脑反复请求会变成死循环,因此需要设置一个变量在config中,请求过刷新接口之后设置这个变量为true,这样就不会重复刷新了。
代码
http.js内容如下:
import axios from "axios"
import {Loading, Message} from "element-ui"
import qs from "qs";
import store from "../store/index"
import router from "../router/index"
// axios 配置
axios.defaults.timeout = 5000
axios.defaults.baseURL = "api/"
//用来处理刷新token后重新请求的自定义变量
axios.defaults.isRetryRequest = false
//刷新token的请求方法
function getRefreshToken() {
//refresh_token使用vuex存在本地的localstorage,之后会详细说
let params = {
grant_type: "refresh_token",
refresh_token: store.state.currentUser.UserRefreshToken
};
//qs的使用主要是因为该接口需要表单提交的方式传数据,具体使用方法自行百度
return axios.post("oauth/token", qs.stringify(params));
}
// http request 拦截器
var loadinginstace;
axios.interceptors.request.use(
config => {
//获取储存在本地的token值
let authToken = store.state.currentUser.UserToken;
//这边可根据自己的需求设置headers,我司采用basic基本认证
if (authToken === null) {
authToken = window.btoa("nucleus" + ":" + "nucleus-secret");
config.headers.Authorization = `Basic ` + authToken;
config.headers["Content-Type"] = "application/x-www-form-urlencoded";
}
else {
config.headers.Authorization = `Bearer ` + authToken
}
//这是element-ui的效果,全页面遮罩,中间带有加载圈
loadinginstace = Loading.service({fullscreen: true})
return config
},
err => {
//这边是参考上面的链接的,具体有什么用我目前还没测到,反正加载超时不是在这边显示
loadinginstace.close()
Message.error({
message: "加载超时"
})
return Promise.reject(err)
}
);
// http response 拦截器
axios.interceptors.response.use(
response => {
//关闭遮罩层,非常重要,不然页面都不能操作了!
loadinginstace.close();
return response
},
err => {
if (err.response) {
switch (err.response.status) {
case 401:
let config = err.config;
/*用vuex删除token
*因为刷新token的接口和登录接口一样
*用basic认证和表单提交的方式
*需要区别于普通接口调用*/
store.dispatch("DelToken");
//判断是否已经刷新过token
if (!config.isRetryRequest) {
return getRefreshToken()
.then(function (res) {
let data = res.data;
//用vuex重新设置基本信息
store.dispatch("UserLogin", {
username: store.state.currentUser.UserName,
token: data.access_token,
refresh_token: data.refresh_token
});
//修改flag
config.isRetryRequest = true;
//修改原请求的token
let authToken = store.state.currentUser.UserToken;
config.headers.Authorization = `Bearer ` + authToken;
/*这边不需要baseURL是因为会重新请求url
*url中已经包含baseURL的部分了
*如果不修改成空字符串,会变成"api/api/xxxx"的情况*/
config.baseURL = "";
//重新请求
return axios(config);
})
.catch(function () {
//刷新token失败只能跳转到登录页重新登录
store.dispatch("UserLogout");
router.replace({
path: "login",
query: {redirect: router.currentRoute.fullPath}
});
throw err;
});
}
break;
}
}
else{
Message.error({
message: "加载超时"
})
}
loadinginstace.close();
return Promise.reject(err)
}
);
export default axios
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: MFC嵌入浏览器框架CEF
- 下一篇: Vue——axios基本配置及请求拦截