每个请求都需要携带 token ,所以我们可以使用 axios request 拦截器,在这里,我们给每个请求都加 token,这样就可以节省每个请求再一次次的复制粘贴代码。
token 失效问题,当我们token 失效,我们服务端会返回一个特定的错误表示,比如 token invalid,但是我们不能在每个请求之后去做刷新 token 的操作呀,所以这里我们就用 axios response 拦截器,我们统一处理所有请求成功之后响应过来的数据,然后对特殊数据进行处理,其他的正常分发。

  1. // 给axios添加一个请求拦截器,
  2. axios.interceptors.request.use(config =>{
  3. // 为请求头添加一个Authorization属性,值为token
  4. // 这样后,当你请求别的接口时服务器就会先判断你的请求头中有没有Authorization这个属性,
  5. // 如果没有,就会驳回你的请求.
  6. config.headers.Authorization = window.sessionStorage.getItem('token');
  7. // 在最后必须return一个cofig
  8. return config
  9. })

配置后哪些需要权限的请求就可以通过了

axios二次封装

  1. import axios from 'axios'
  2. import { MessageBox, Message } from 'element-ui'
  3. import storage from './storage'
  4. import config from '@/config/index'
  5. import router from '@/router/index'
  6. // 创建axios对象,并设置请求信息,用于设置请求拦截器
  7. const service = axios.create({
  8. // 配置请求基础地址
  9. baseURL: config.baseApi,
  10. // 设置请求超时时间
  11. timeout: 5000
  12. })
  13. // 请求拦截
  14. service.interceptors.request.use(
  15. res => {
  16. // 在每一次请求时携带上token
  17. const Token = storage.getItem('Token')
  18. if (Token) {
  19. res.headers.Token = Token
  20. }
  21. return res
  22. },
  23. error => {
  24. // do something with request error
  25. console.log(error) // for debug
  26. return Promise.reject(error)
  27. }
  28. )
  29. service.interceptors.response.use(
  30. res => {
  31. const { code, data, message } = res.data
  32. // token未过期时,返回的数据
  33. if (code === 200) {
  34. return data
  35. } else {
  36. // token过期时返回的数据
  37. if (code === 401) {
  38. MessageBox.alert('登录已过期,请重新登录!')
  39. router.push({ path: '/' })
  40. } else if (code === 403) {
  41. MessageBox.alert('您没有访问权限')
  42. } else if (code === 404) {
  43. MessageBox.alert('访问失败,请检查网络')
  44. } else if (code === undefined) {
  45. return res.data
  46. } else {
  47. MessageBox.alert(message, '警告', {
  48. confirmButtonClass: 'el-button--myPrimary',
  49. type: 'warning'
  50. })
  51. }
  52. return Promise.reject(new Error('error'))
  53. }
  54. },
  55. error => {
  56. Message({
  57. message: error.message,
  58. type: 'error',
  59. duration: 5 * 1000
  60. })
  61. return Promise.reject(error)
  62. }
  63. )
  64. // 封装request请求
  65. function request (options) {
  66. // 设置默认数据
  67. options.method = options.method || 'get'
  68. options.baseURL = options.baseURL || ''
  69. if (options.method.toLowerCase() === 'get') {
  70. options.params = options.data
  71. }
  72. // if (config.env === 'prod') {
  73. // service.defaults.baseURL = config.baseApi
  74. // } else {
  75. // service.defaults.baseURL = config.mock ? config.mockApi : config.baseApi
  76. // }
  77. // 设置基础路径地址,根据不同的接口设置不同的基础路径
  78. service.defaults.baseURL = options.baseURL
  79. // 将数据传递给axios对象,并返回
  80. return service(options)
  81. }
  82. // 给request对象创建不同类型的函数,这样使用时就可以通过request.get(url, data, options){}的方式使用
  83. ['get', 'post', 'put', 'delete', 'patch'].forEach(item => {
  84. request[item] = (url, data, options) => {
  85. //返回一个请求接口对象
  86. return request({
  87. url,
  88. data,
  89. method: item,
  90. ...options
  91. })
  92. }
  93. })
  94. // 导出axios对象,二次封装后的对象
  95. export default request

自动刷新token

  1. Vue.use(Vuex)
  2. Vue.use(VueAxios, axios)
  3. Vue.use(qs)
  4. 注:qs,。
  5. request 拦截器实现
  6. axios.interceptors.request.use(
  7. config => {
  8. config.baseURL = '/api/'
  9. config.withCredentials = true // 允许携带token ,这个是解决跨域产生的相关问题
  10. config.timeout = 6000
  11. let token = sessionStorage.getItem('access_token')
  12. let csrf = store.getters.csrf
  13. if (token) {
  14. config.headers = {
  15. 'access-token': token,
  16. 'Content-Type': 'application/x-www-form-urlencoded'
  17. }
  18. }
  19. if (config.url === 'refresh') {
  20. config.headers = {
  21. 'refresh-token': sessionStorage.getItem('refresh_token'),
  22. 'Content-Type': 'application/x-www-form-urlencoded'
  23. }
  24. }
  25. return config
  26. },
  27. error => {
  28. return Promise.reject(error)
  29. }
  30. )
  31. //在 response 拦截器实现
  32. axios.interceptors.response.use(
  33. response => {
  34. // 定时刷新access-token
  35. if (!response.data.value && response.data.data.message === 'token invalid') {
  36. // 刷新token
  37. store.dispatch('refresh').then(response => {
  38. sessionStorage.setItem('access_token', response.data)
  39. }).catch(error => {
  40. throw new Error('token刷新' + error)
  41. })
  42. }
  43. return response
  44. },
  45. error => {
  46. return Promise.reject(error)
  47. }
  48. )