Published on

前后端分离鉴权:token和axios请求响应拦截器

Authors
  • avatar
    Name
    Hansuku
    Twitter

首先来看一下设计思路 后端使用的是laravel5.5,搭配jwt-auth来做 CORS 跨域,每个请求前端都需要在请求头里带token,并且存储到本地localStoragetoken在服务端默认八小时过期,到还剩 2 小时的时候后端会在这段时间内的请求响应头里返回新的token,前端拿到新的token更新本地token 整体流程看起来不复杂,并且项目里本身就在使用axios 设置拦截器起来还是轻松的

// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

import axios from 'axios'
Vue.prototype.$axios = axios

Vue.config.productionTip = false

import MetaInfo from 'vue-meta-info'
Vue.use(MetaInfo)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>',
  created() {
    //axios请求响应拦截器
    this.$axios.interceptors.request.use(
      //拦截请求
      (config) => {
        //console.log(this.$store.state.token)
        if (localStorage.getItem('token')) {
          //查询本地是否存在token
          config.headers.Authorization = localStorage.getItem('token') //在请求头里设置token
        }
        return config
      },
      (err) => {
        return Promise.reject(err)
      }
    ),
      this.$axios.interceptors.response.use(
        //拦截响应
        (response) => {
          var token = response.headers.authorization
          if (token) {
            //查询响应头里是否存在token
            this.$store.dispatch('refreshToken', token) //存在则调用store替换本地token 可以根据自己的业务 更简单的做法是直接在这里替换localStorage的token
          }
          return response
        },
        (error) => {
          console.log(error)
          return Promise.reject(error)
        }
      )
  },
})

需要注意的是,在加入了Authorization的请求头以后,我们发出的http请求就不再属于简单请求并且自定义请求头,浏览器会在真正的请求之前做一次option请求,来询问实际发送的请求是否是安全的/可用的 另外后端在响应头里返回 token 时,可能会存在前端能在浏览器里的network里看到Authorization,但是响应拦截器里获取不到response.headers.authorization的情况,这个原因是 W3C 制定的跨域规则中,只允许后端和浏览器之间得到允许的数据,所以需要后端设置 header add_header 'Access-Control-Allow-Origin' '*'; 当然了 *号部分可以是填上某个专有的,比如我只想要Authorization可以获取到,那么这里就可以只填这项,具体的可以看一下 MDN 上对于Access-Control-Allow-Origin的解释:点这里查看

*/}