SoFunction
Updated on 2025-04-12

Vue axios obtains token temporary token encapsulation case

Preface

Why do you have to write this blog? Because this incident makes me feel good about the balls. Don't ask the rest, I won't say anything else. Because I don’t want to (don’t bother) to draw the flow chart.

Development architecture

Front-end page: Vue

Network request: Axios; Method: vue add axios

Cache Scheme

Global variable: Vuex

Local Cache: LocalStorage

Technology dependency

you guess?

background

The company develops a web page embedded in the App, and uses the old routine in terms of security: the App passes parameters to the front-end (including signatures) through the URL, and the front-end passes the parameters to the H5 back-end to verify the signature. After the matter is done, the front-end decides whether the user is legal. In addition, N JS methods front-ends are defined to determine whether they are called by Android or Apple based on fixed GET parameters.

Preliminary concept

The preliminary idea about the token design plan is as follows: when you enter the first time, get the token, and the backend checks whether the signature is passed. If you do not pass, please enter the page from the legal channel and do not disappear.

Otherwise, the user can continue to follow-up operations until the backend returns the token expiration specific status code and returns the frontend calls the JS method to re-get the URL parameters and request the token when the user is unconscious. After the matter is finished, the user's request operation will continue. (To avoid users using old tokens to manipulate data elsewhere, each time they get the token, they re-get and verify from the App, instead of refreshing and returning the new token in the interface)

Exciting things

There is no version control when defining URL parameters in the first phase, resulting in the new JS method iterative version added to the front-end page called the unknown method page without any response; I don’t know how many periods of the data it was...

In order to avoid the 1 request change 3 requests caused by token expiration during the request process, the asynchronous method of token time needs to be checked before each request (if the token expires, getToken is called to get the new token and store it locally) causing block nesting.

I won’t talk about N methods later...

Upgrade ideas

Let’s not talk about the version or something. For this token issue, I can’t copy and paste every time I add a new request, right? It can annoy people! Then I can only judge the token timeliness before the axios request.

Go straight to the topic

Function declaration

getToken: Get the stored token from local

checkToken: Check the token time, if the failed call to refreshToken function is successful, it will be stored locally, otherwise the error reason will be returned

refreshToken: Call JS method to get signature parameters from the App and request token again

Things to note

When the token expires during the checkToken process, first remove the local expired token cache data.

/* eslint-disable no-console */
/* eslint-disable no-unused-vars */
"use strict";

import Vue from 'vue';
import axios from "axios";
import { getToken } from '../utils/'
import { checkToken, refreshToken, clearCache } from "../utils/";

// Full config: /axios/axios#request-config
//  =  ||  || '';
// ['Authorization'] = AUTH_TOKEN;
// ['Content-Type'] = 'application/x-www-form-urlencoded';
["Content-Type"] = "application/json";

let cancel,
 promiseArr = {};
let config = {
 baseURL: .VUE_APP_BASE_URL,
 timeout: 8 * 1000, // Timeout
 withCredentials: true, // Check cross-site Access-Control
};

const _axios = (config);

_axios.(
 function (config) {
  // Do something before request is sent
  let token = getToken();
  // alert("token1:" + token);
  // When starting a request, cancel the same request currently in progress  if (promiseArr[]) {
   promiseArr[]("Please wait");
   promiseArr[] = cancel;
  } else {
   promiseArr[] = cancel;
  }
  if (token) {
   return checkToken(null)
     .then((result) => {
      // ("refreshToken result:", result);
      if (result === true) {
       token = getToken()
       // alert("token2:" + token);
       ["authorization"] = token;
       return config;
      } else {
       return (Error(result))
      }
     }).catch((err) => {
      // Terminate this request      return (err);
     });
  }
  return config;
 },
 function (error) {
  // Do something with request error
  return (error);
 }
);

// Add a response interceptor
_axios.(
 function (response) {
  // Do something with response data
  let { status, statusText, data } = response;
  if (err_check(status, statusText, data) && data) {
   // var randomColor = `rgba(${parseInt(() * 255)},${parseInt(
   //  () * 255
   // )},${parseInt(() * 255)})`;

   // (
   //  "%c┍------------------------------------------------------------------┑",
   //  `color:${randomColor};`
   // );
   // ("| Request address: ", );   // ("| Request parameters: ", );   // ("| Return data: ", );   // (
   //  "%c┕------------------------------------------------------------------┙",
   //  `color:${randomColor};`
   // );
   if ( === "0001") {
    clearCache()
    var config = ;
    var url = ;
    url = ("/apis", "").replace(.VUE_APP_BASE_URL, "")
     = url;
    // alert((config))
    return refreshToken(null)
     .then((result) => {
      // ("refreshToken result:", result);
      if (result == true) {
       let token = getToken()
       if (token) {
        ["authorization"] = token;
       }
       return axios(config)
        .then((result) => {
        let { status, statusText, data } = result;
        // ('Interface quadratic request result:', result);        if (err_check(status, statusText, data) && data) {
         return (data)
        } else {
         return (Error());
        }
       }).catch((err) => {
        // ('Interface secondary request err:' + err);        return (err);
       });
      } else {
       // alert("result:" + result)
       return (Error())
      }
     }).catch((err) => {
      // Terminate this request      // alert("Terminate this request:" + )      // ("refreshToken err:", err);
      return (err);
     });
   } else {
    return (data);
   }
  } else {
   return (Error(statusText));
  }
  // return response;
 },
 function (error) {
  // Do something with response error
  // ("error", error);
  return (error);
 }
);

// eslint-disable-next-line no-unused-vars
const err_check = (code, message, data) => {
 if (code == 200) {
  return true;
 }
 return false;
};

 = function (Vue, options) {
  = _axios;
  = _axios;
 (, {
  axios: {
   get() {
    return _axios;
   }
  },
  $axios: {
   get() {
    return _axios;
   }
  },
 });
};

(Plugin)
export default Plugin;

Supplementary knowledge:vue+ axios+token encapsulate axios encapsulate interface url with token request, token invalid refresh

1. Encapsulate axios

import axios from 'axios'
import qs from "qs" 
const TIME_OUT_MS = 60 * 1000 // Default request timeout time// = 'http://localhost:8080'; 
 
// http request interceptor(
  config => {
    if ($("access_token")) { // Determine whether token exists. If it exists, add tokens for each http header       ='Bearer '+ $("access_token");
    }
    return config;
  },
  err => {
    return (err);
}); 
 
// http response interceptor(
  response => {
    return response;
  },
  error => {
    ("response error :"+error);
    if () {
      switch () {
        case 401:
          ("token expired");
          var config = ;
          refresh(config);
          return;
      }
    }
    return (error)  // Return the error message returned by the interface  });
/*
 *Refresh token
 */
function refresh(config){
  var refreshToken = $("refresh_token");
  var grant_type = "refresh_token";
  axios({
    method: 'post',
    url: '/oauth/token',
    data: handleParams({"grant_type":grant_type,"refresh_token":refreshToken}),
    timeout: TIME_OUT_MS,
    headers: {}
  }).then(
    (result) => {
      if(.access_token){  //Resave token        $("access_token",.access_token);
        $("refresh_token",.refresh_token);
        //Re-execution is required        axios(config);
      }else{ 
 
        //this.$('goto', 'login');
        ();
      }
    }
  ).catch((error) => {
    //this.$('goto','login');
    ();
  });
}
/*
 * @param response Returns the data list
 */
function handleResults (response) { 
 
  var result = {
    success: false,
    message: '',
    status: [],
    errorCode: '',
    data: {}
  }
  if ( == '200') {
     = ;
     = ;
     = true;
  }
  return result
} 
 
// function handleUrl (url) {
//   //url = BASE_URL + url
//   url =root +url;
// // BASE_URL is the ip prefix of the interface, such as http:10.100.1.1:8989///   return url
// } 
 
/*
 * @param data parameter list
 * @return
 */
function handleParams (data) {
  return (data);
} 
export default {
  /*
    * @param url
    * @param data
    * @param response The callback function when the request is successful
    * @param exception callback function
    */
  post (url, data, response, exception) {
    axios({
      method: 'post',
      //url: handleUrl(url),
      url: url,
      data: handleParams(data),
      timeout: TIME_OUT_MS,
      headers: {
        //'Content-Type': 'application/json; charset=UTF-8'
      }
    }).then(
      (result) => {
        response(handleResults(result))
      }
    ).catch(
      (error) => {
        if (exception) {
          exception(error)
        } else {
          (error)
        }
      }
    )
  },
  /*
    * get request
    * @param url
    * @param response The callback function when the request is successful
    * @param exception callback function
    */
  get (url,data, response, exception) {
    axios({
      method: 'get',
      url: url,
      params:data,
      timeout: TIME_OUT_MS,
      headers: {
        'Content-Type': 'application/json; charset=UTF-8'
      }
    }).then(
      (result) => {
        response(handleResults(result))
      }
    ).catch(
      (error) => {
        ("error"+response);
        if (exception) {
          exception(error)
        } else {
          (error)
        }
      }
    )
  }
}

2. Configure axios cross-domain and request baseUrl

-->

'
'use strict'
// Template version: 1.3.1
// see /webpack for documentation. 
 
const path = require('path') 
 
//Introduce cross-domain configurationvar proxyConfig = require('./proxyConfig') 
 = {
  dev: { 
 
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    //proxyTable: {}, //The default cross-domain configuration is empty    proxyTable: , 
 
    // Various Dev Server settings
    host: 'localhost', // can be overwritten by 
    port: 8886, // can be overwritten by , if port is in use, a free one will be determined
    autoOpenBrowser: false,
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, // /configuration/dev-server/#devserver-watchoptions- 
 
    /**
     * Source Maps
     */ 
 
    // /configuration/devtool/#development
    devtool: 'cheap-module-eval-source-map', 
 
    // If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // /en/#cachebusting
    cacheBusting: true, 
 
    cssSourceMap: true
  },
  
  build: {
    // Template for 
    index: (__dirname, '../dist/'),
 
 
    // Paths
    assetsRoot: (__dirname, '../dist'),
    assetsSubDirectory: 'static',
    // When the project name changes, it needs to be changed here. Originally assetsPublicPath: '.'    assetsPublicPath: './', 
 
    /**
     * Source Maps
     */ 
 
    productionSourceMap: true,
    // /configuration/devtool/#production
    devtool: '#source-map', 
 
    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
 
 
    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: .npm_config_report
  }
}

Create a file in the directory File

={
  proxy:{
    '/':{ //Map localhost:8081 to /apis      target:'http://localhost:8080',//Interface address      changeOrigin: true,// If the interface crosses the domain, this parameter configuration is required      secure:false, //If the interface is an HTTPS interface, it needs to be set to true      pathRewrite:{
        '^/':''
      }
    }
  }
}

3. Encapsulate API request Url

export default {
  oauth: {
    login: '/oauth/token', // Log in    logout: '/oauth/logout' // // quit  },
  user: {
    addUser: '/user/add',
    updateUser: '/user/update',
    getUser:'/user/', //+ Id
    exists:'/exists/', // +id
    enable:'/enable/', // +id
    disable:'/disable/', // +id
    delete:'/delete/',  //+id
    password:'/password ',
    query:'/query'
  }
}

IV. Introduce

import http from './plugins/'
import ports from './plugins/ports'
 = http
 = ports

V. Use

Used in

login() {
  (,{username:,
    password:,grant_type:'password'}, res => {
    if () {
    // Return to the correct processing    Page jump
    this.$('goto', 'edit');
  } else {
    // Return error handling    //alert("waiting for processing");  }
},err =>{
    //("Processing"+);    if(=='400'){
      //Incorrect display of username or password      this.$();
      this.$();
    }
  })
   
}

The above example of Vue axios obtaining token temporary token encapsulation is all the content I share with you. I hope you can give you a reference and I hope you can support me more.