1.请求基地址
- 在src中新建api文件夹,新建一个user.js文件,导入设置了基地址的请求对象,再封装一个做登录的接口函数
- 来到src/api文件夹,新建index.js,做统一出口
- 最后来到login 页,导入上面封装的接口
- 修改:设置背景颜色、并添加!import优先级,设置字体颜色
- 在src目录新建发送请求的页面并导入封装好的请求
2.请求头的设置
- 传递一个对象参数
- 创建一个特定的Axios实例
- 使用Axios拦截器
在向服务器发送请求时,很多请求都需要在请求头中携带token,每一次去请求都写请求头很麻烦,所以我们写一个请求拦截器,统一拦截并添加一个请求头
// 请求拦截器
request.interceptors.request.use((config) => {
// Do something before request is sent
// 在我们发送请求前做的事情
// 判断发送的请求需不需要请求头
if (store.state.tokenObj.token) {
// 统一在请求头中携带token
config.headers.Authorization = 'Bearer ' + store.state.tokenObj.token
}
return config
}, (error) => {
// Do something with request error
// 请求失败
return Promise.reject(error)
})
3.请求拦截器和响应拦截器
- 请求拦截器
请求拦截器的作用是在请求发送前进行一些操作,例如在每个请求体里加上token,统一做了处理如果以后要改也非常容易。
- 响应拦截器:
响应拦截器的作用是在接收到响应后进行一些操作,例如在服务器返回登录状态失效,需要重新登录的时候,跳转到登录页。响应拦截器也是一样如此,就是在请求结果返回后,先不直接导出,而是先对响应码等等进行处理,处理好后再导出给页面,如果将这个对响应码的处理过程抽出来,就成了所谓的响应拦截器;
4.token过期问题处理
Token用于进行接口鉴权,但是Token具有由后端设置的过期时间,当Token过期以后,就无法再请求数据了
项目中后端设置的过期时间为24h,测试时我们可以手动修改token值让Token失效
处理方式:
- 方式1:用户重新登录,获得新的Token就可以了,但是当过期时间较短的时候,每次都是要重新登录操作 的,体验很差
为了提高用户的信息安全性,Token的过期时间都比较短(就算万一泄露了,过一会儿也就过期无效化了)
- 方式2:根据用户信息,自动给用户生成新的Token,减少登录次数
5.无感刷新
前端登录后,后端返回token
和token有效时间
,当token过期时要求用旧token去获取新的token,前端需要做到无痛刷新token,即请求刷新token时要做到用户无感知。
方法一:
在请求发起前拦截每个请求,判断
token
的有效时间是否已经过期,若已过期,则将请求挂起,先刷新token
后再继续请求。
- 优点: 在请求前拦截,能节省请求,省流量。
- 缺点: 需要后端额外提供一个token过期时间的字段;使用了本地时间判断,若本地时间被篡改,特别是本地时间比服务器时间慢时,拦截会失败。
不在请求前拦截,而是拦截返回后的数据。先发起请求,接口返回过期后,先刷新
token
,再进行一次重试。
- 优点:不需额外的token过期字段,不需判断时间。
- 缺点: 会消耗多一次请求,耗流量。
6.refresh_token过期处理
当使用token失效或者即将失效的时候,我们需要用刷新token发现ajax请求去获取一个新的token来代替之前使用的token。由于ajax是异步的,请求新的token需要一定的时间,在此时我们去请求接口,就会出现用旧token发送请求,导致401鉴权失败问题。
解决方法
使用 try{}catch{}处理失败的情况
把整段请求代码放进try代码里进行检验
try{
//发送请求,获取refresh_token
let res = await axios({
url: 'http://geek.itheima.net/v1_0/authorizations',
method: 'put',
//请求头
headers: {
Authorization: 'Bearer ' + store.state.tokenObj.refres_token
}
})
//调用store里的changeToken方法,修改初始token
store.commit('changeToken', {
// 使用第三次请求中打的到的新的token替换原本的token
token: res.data.data.token,
// refres_token依然是原本的值
refres_token: store.state.tokenObj.refres_token
})
// 这个时候把获取用户信息这个请求再发了一次
// 在请求拦截器中,拦截器return什么,浏览器就拿到什么
return request(error.config)
// console.log('第三次请求获取到的内容', res);
}catch{
Toast.fail('登录状态失败,重新登陆')
// 返回登录页
router.push('./login')
}