登录的请求拦截和响应拦截设置

原因:设置请求拦截器的目的其实是为了在访问别的页面之前不需要每次都单独设置token,所以就在请求拦截器中配置,这样每次请求访问时都会带上token。还有一种情况,是设置一个token的失效时间,防止用户长时间忘记操作忘记退出登录而导致数据泄露等情况,所以就需要在请求头带上token;

实现程序代码:

// 引入 axios 库
import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import router from '@/router'

// 创建 axios 实例
const service = axios.create({
  // process.env 是脚手架工具获取环境变量的属性
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

const checkTimeout = () => {
  // 之前是判断到有 token 就带上 token
  // 由于需要被动介入, 还要检查超时文成
  const timeout = 1000 * 60 * 60 * 2
  const now = Date.now()
  const loginTime = localStorage.getItem('timestamp')
  return now - loginTime > timeout
}

// 请求拦截器, 给每个接口都带上 token
// 拦截到的形参一般叫 config 当前请求的配置
// 登录接口例外, 其实就是必须登陆过有 token 才能带上
service.interceptors.request.use(config => {
  if (store.getters.token) {
    if (checkTimeout()) {
      // 清理数据, 跳转登录页, 阻止当前请求
      store.dispatch('user/logout')
      router.push('/login')
      return Promise.reject(new Error('登录已超时(主动介入)'))
    }
      //设置请求头,带上token
    config.headers.Authorization = 'Bearer ' + store.getters.token
  }
  return config
})
// 导出实例
export default service

同时我们也可以对我们请求回来的数据做处理,根据服务器响应成功,或没有响应等;可以通过响应拦截器对错误统一处理

// 响应拦截器 统一处理错误
// 响应拦截器, 可以接受两个回调, 第一个会拦截到网络成功
// 第二个拦截到的是网络失败
service.interceptors.response.use(res => {
  // 成功返回数据
  if (res.data.success) {
    // 请求成功数据也没问题, 返回最终的结果
    return res.data.data
  } else {
    // 网络请求没问题, 响应 200 但是后端说 数据层面出了问题
    // 提示用户
    Message.error(res.data.message)
    // 阻止当前请求
    // throw new Error(res.data.message)
    return Promise.reject(new Error(res.data.message))
  }
}, err => {
  // 网络请求完全失败, 如写错 url, 或者断网, 或者服务器崩溃
  // 提示用户
  // 阻止当前请求
  console.dir(err)
  // 这里的错误可能性很多, 之前是统一进行处理
  // 现在要处理一种独特情况, 后端告诉我们 token 失效
  // 注意由于错误可能性太多, 比如断网, 服务器崩溃的情况下,
  // 可能连 response 都没有, 为了防止出 undefined 取值的问题
  // 先确认 response 存在再做 token 验证
  if (err.response && err.response.data.code === 10002) {
    store.dispatch('user/logout')//退出登录
    router.push('/login')//回登录页
  }

  Message.error(err.message)
  // throw err
  return Promise.reject(err)
})

小结:

  • 请求拦截器:其实就是先执行要添加的数据,然后再执行Ajax,如果把这个添加数据的过程抽出来,就成了所谓的请求拦截器了
  • 响应拦截器:就是在请求结果的返回后的同时,先不直接导出,而是先对响应码等进行处理,处理好之后再导出给页面,如果将这个对象响应码的处理过程抽出来,就成了所谓的响应拦截器