vuex移动端项目中对token的过期的处理
1. 背景知识了解出于安全考虑,我们通过登陆操作获取到的token一般都会有一个有效时间,如果一直是静默状态,没有接口调用操作,时间到了之后token会失效,失效之后的token是不能作为用户的有效标识再去请求数据的,如果使用失效的token去请求接口数据,一般会报出401状态码2. 开发者需要做什么当用户并不知道token已经失效的情况下,继续进行操作,会出现401的状态,如果我们什么都不做,用
1. 背景知识了解
出于安全考虑,我们通过登陆操作获取到的token一般都会有一个有效时间,如果一直是静默状态,没有接口调用操作,时间到了之后token会失效,失效之后的token是不能作为用户的有效标识再去请求数据的,如果使用失效的token去请求接口数据,一般会报出401状态码
2. 开发者需要做什么
当用户并不知道token已经失效的情况下,继续进行操作,会出现401的状态,如果我们什么都不做,用户并不能知道当前发生了什么,所以我们有必要去帮助用户去获取新的token来替换失效的token,获取新token的方式一般有俩种,分别为:
- 强制用户跳回登录页进行登录,让用户通过登录操作进行新token获取(一般做法)
- 无感知刷新token 这种方案偏复杂,但是用户体验好,整体原理是,登录成功之后,我们会获取到俩个token数据,一个为当前token,一个为专门为了刷新token所需要的refreshToken,refreshToken的失效时间要远长于token,所以我们可以通过refreshToken去获取新的token,而不需要进行路由跳转跳回到登录页
接下来,我们分别看一下,俩种方案下的具体实施
3. 跳回登录页
原理
当token过期之后,我们使用过期token调用一个接口时,会返回401的状态码,我们一旦监听到当前是401的状态,就跳回到登录页,要求重新登录获取有效token
模拟token过期失效
我们正常登陆应用,然后随便打开一片文章,文章数据的获取是需要token的,然后我们去application中把token的部分删掉一部分,它就会变成无效token,回调详情页刷新浏览器让接口重新发起,然后查看接口状态
// utils/request.js
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response
}, function (error) {
// 对响应错误做点什么
console.log(error.response.status) // 401
if (error.response.status === 401) {
router.push({
path: '/login'
})
}
return Promise.reject(error)
})
4.哪里出问题回到哪里
我们的接口是在哪个页面出现的401状态,等到用户重新登录之后,我们希望他能够回到刚才的页面,这就需要我们在跳回到登录页的时候,不光是跳转,还需要记录一下页面信息
1.跳转之前记录页面信息
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response
}, function (error) {
// 对响应错误做点什么
console.log(error.response.status) // 401
if (error.response.status === 401) {
router.push({
path: '/login',
// 拿到当前页面完成路径包括参数,再跳转过去
query: {
backto: router.currentRoute.fullPath
}
})
}
return Promise.reject(error)
})
2.登录之后先判断再跳转
// 判断当前是否有sourceFrom字段 如果有则优先跳回到记录页
const backto = this.$route.query.backto
if (backto) {
this.$router.push({
path: backto
})
} else {
this.$router.push({
path: '/'
})
}
5.无感知刷新token *
对于某次请求A,如果是401错误,我们使用refreshToken
(后台接口返回的2个token,这是另外一个,专门用来做token过期的) 去获取新token
- 新token请求成功
- 更新本地token
- 以之前的请求参数再发一次请求A
- 新token请求失败(refreshtoken也失效了)
- 清空vuex中的token
- 携带请求地址,跳转到登陆页
// request.js
import store from '@/store'
import router from '@/router'
// 全局响应拦截
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response
}, async function (error) {
// 对响应错误做点什么
if (error.response && error.response.status === 401) {
const refreshToken = store.state.tokenInfo.refresh_token
// 如果try语法块中出现错误,证明refreshToken也无效了
try {
const result = await axios({
method: 'PUT',
url: 'http://toutiao-app.itheima.net/v1_0/authorizations',
headers: {
Authorization: `Bearer ${refreshToken}`
}
})
const newToken = result.data.data.token
store.commit('setToken', {
refresh_token: refreshToken,
token: newToken
})
// 重新使用我们之间创建的axios实例,用本次错误请求中的配置项,再发一次
return instance(error.config)
} catch {
// 路由跳转,进入登陆页
router.push({
path: '/login',
query: {
// currentRoute:表示当前路由
backto: router.currentRoute.fullPath
}
})
}
}
return Promise.reject(error)
})
以下只是个人做的小案例中常出现的问题,拿出来与大家分享。
更多推荐
所有评论(0)