有如下两种情况会出现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) {
// 如果发生了错误,判断是否是401
console.dir(error)
if (error.response.status === 401) {
// 开始处理
console.log('响应拦截器-错误-401')
const refreshToken = store.state.tokenInfo.refresh_token
// if (有refresh_token) {
if (refreshToken) {
// 1. 请求新token
try {
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. 保存到vuex
store.commit('mSetToken', {
refresh_token: refreshToken,
token: res.data.data.token
})
// 3. 重发请求
// request是上面创建的axios的实例,它会自动从vuex取出token带上
return request(error.config)
} catch (error) {
// 清除token
store.commit('mSetToken', {})
// 去到登录页(如果有token值,就不能到login)
const backtoUrl = encodeURIComponent(router.currentRoute.fullPath)
router.push('/login?backto=' + backtoUrl)
return Promise.reject(error)
}
} else {
// 去到登录页
// 清除token
store.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实例+