有如下两种情况会出现401错误:
- 未登陆用户做一些需要权限才能做的操作(例如:关注作者),代码会报出401错误。这种情况下,应该让用户回到登陆页。
- 登录用户的token过期了 ( token会有有效期(具体是多长,是由后端决定))
refresh_token的作用
- 作用: 当token的有效期过了之后,可以使用它去请求一个特殊接口(这个接口也是后端指定的,明确需要传入refresh_token),并返回一个新的token回来(有效期还是2小时),以替换过期的那个token。
- 有效期:14天。(最理想的情况下,一次登陆可以持续14天。
request的响应拦截器中:
- 对于某次请求A,如果是401错误 (2)
- 有refresh_token,用refresh_token去请求回新的token (3)
- 新token请求成功 (4)
- 更新本地token (5)
- 再发一次请求A (6)
- 新token请求失败
- 携带请求地址,跳转到登陆页
- 新token请求成功 (4)
- 没有refresh_token,说明没有登陆
- 携带请求地址,跳转到登陆页
- 有refresh_token,用refresh_token去请求回新的token (3)
代码:
在src\utils\request.js中,补充响应拦截器。
要进行路由跳转,所以要引入/router/auth.js中的路由
import router from '../router/auth.js'// 响应拦截器
request.interceptors.response.use(function (response) {console.log('响应拦截器', response)return response
}, async function (error) {// 如果发生了错误,判断是否是401console.dir(error)if (error.response.status === 401) {// 开始处理console.log('响应拦截器-错误-401')const refreshToken = store.state.tokenInfo.refresh_token// if (有refresh_token) {if (refreshToken) {// 1. 请求新tokentry {const res = await axios({url: 'http://localhost:8000/v1_0/authorizations',method: 'PUT',headers: {Authorization: `Bearer ${refreshToken}`}})console.log('请求新token', res.data.data.token)// 2. 保存到vuexstore.commit('mSetToken', {refresh_token: refreshToken,token: res.data.data.token})// 3. 重发请求// request是上面创建的axios的实例,它会自动从vuex取出token带上return request(error.config)} catch (error) {// 清除tokenstore.commit('mSetToken', {})// 去到登录页(如果有token值,就不能到login)const backtoUrl = encodeURIComponent(router.currentRoute.fullPath)router.push('/login?backto=' + backtoUrl)return Promise.reject(error)}} else {// 去到登录页// 清除tokenstore.commit('mSetToken', {})const backtoUrl = encodeURIComponent(router.currentRoute.fullPath)router.push('/login?backto=' + backtoUrl)return Promise.reject(error)}} else {return Promise.reject(error)}
})
注意点:
- router.currentRoute: 表示当前路由对象,如果是在.vue中,就可以用this.$route。
- 响应拦截器要加在axios实例 request上。
- 用refresh_token请求新token时,要用axios,不要用实例request
- 得到新token之后,再发请求时,要用request实例+