preface

Before we talk about token validation, let’s talk about vue-Router’s navigational guard and AXIos interceptor.

Vue-router Navigation guard

The so-called “navigation” is that the route is changing. Router.beforeeach () The global front-guard verifies the current state before a route jump, for example, verifying the user’s login status, and effectively intercepts if the user is not logged in.

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) = > {
  // ...
})
Copy the code

Axios interceptor

Axios interceptors are divided into request interceptors and response interceptors, which intercept requests or responses before they are processed by THEN or catch, i.e. triggered when the front-end page sends a request to the back-end.

// Add request interceptor
axios.interceptors.request.use(function (config) {
	// What to do before sending the request
    return config;
}, function (error) {
    // What to do about the request error
    return Promise.reject(error);
});

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // all status codes in the 2xx range trigger this function.
    // What to do with the response data
    return response;
}, function (error) {
    // Any status code outside the 2xx range triggers this function.
    // Do something about the response error
    return Promise.reject(error);
});
Copy the code

If you need to remove interceptors later, you can do this:

const myInterceptor = axios.interceptors.request.use(function () {/ *... * /});
axios.interceptors.request.eject(myInterceptor);
Copy the code

The difference between

The navigational guard is more like a route-level interception, whereas the Axios interceptor is an interface level interception, which is the essential difference between them.

A more detailed distinction between them will be mentioned in the following article, which will not be discussed here, because knowledge points are not brought into the case scenarios for application, which is easy to cause problems that are not deep or difficult to understand, so return to the text first.

The Vue project implements token authentication

401 Unauthorized: This status code indicates that the request sent by a user does not have access permission and requires identity authentication. The response returned with 401 must include a WWW-Authenticate header applicable to the requested resource to challenge the user.

Front-end and back-end separate development is great, but it also brings some thorny problems, such as cross-domain processing, token verification..

Next, let’s talk about token verification.

The general idea of token verification in Vue project is as follows:

  1. On the first login, the front end invokes the login interface of the back end and sends the user name and password
  2. After receiving the request, the backend verifies the validity of the user name and password, and returns a token to the front-end
  3. When the front end gets the token, it stores it inlocalStorage ε’Œ vuexIs displayed, and the route page is displayed
  4. After that, each time the front-end switches to a route, it checks whether there is a token in the localStorage. If there is no token in the localStorage, it switches to the login page; if there is, it switches to the corresponding route page
  5. Each time the front-end invokes the back-end interface, it carries the token in the request header
  6. The backend determines whether there is a token in the request header
    • If a token exists in the header, the validity of the token is verified. If the token succeeds, the data requested by the front-end is returned. Return 401 Unauthorized status on failure (if the token expires)
    • If no token exists in the header, the 401 status code is also returned
  7. If the front-end receives the 401 status code, the token information is cleared and the login page is displayed

Login.vue

<template>
  <div>
    <input type="text" v-model="loginForm.username" placeholder="Username"/>
    <input type="text" v-model="loginForm.password" placeholder="Password"/>
    <button @click="login">The login</button>
  </div>
</template>
 
<script>
import { mapMutations } from 'vuex';
export default {
  data () {
    return {
      loginForm: {
        username: ' '.password: ' '
      },
      userToken: ' '
    };
  },
 
  methods: {
    ...mapMutations(['changeLogin']),
    login () {
      let _this = this;
      if (this.loginForm.username === ' ' || this.loginForm.password === ' ') {
        alert('Account number or password cannot be empty');
      } else {
        this.axios({
          method: 'post'.url: '/user/login'.data: _this.loginForm
        }).then(res= > {
          console.log(res.data);
          _this.userToken = 'Bearer ' + res.data.data.body.token;
          // Save the user token to vuex
          _this.changeLogin({ Authorization: _this.userToken });
          _this.$router.push('/home');
          alert('Login successful');
        }).catch(error= > {
          alert('Wrong account or password');
          console.log(error); }); }}}};</script>
Copy the code

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
 
const store = new Vuex.Store({
  state: {
    / / store token
    Authorization: localStorage.getItem('Authorization')?localStorage.getItem('Authorization') : ' '
  },
  mutations: {
    // Modify the token and store the token to localStorage
    changeLogin (state, user) {
      state.Authorization = user.Authorization;
      localStorage.setItem('Authorization', user.Authorization); }}});export default store
Copy the code

Router /index.js: navigation guard

import Vue from 'vue';
import Router from 'vue-router';
import login from '@/components/login';
import home from '@/components/home';
 
Vue.use(Router);
 
const router = new Router({
  routes: [{path: '/'.redirect: '/login'
    },
    {
      path: '/login'.name: 'login'.component: login
    },
    {
      path: '/home'.name: 'home'.component: home
    }
  ]
});

// Navigational guard: registers a global front-guard with router.beforeEach to determine whether the user is logged in
router.beforeEach((to, from, next) = > {
  if (to.path === '/login') {
    next();
  } else {
    let token = localStorage.getItem('Authorization');
 
    if (token === null || token === ' ') {
      next('/login');
    } else{ next(); }}});export default router
Copy the code

Main.js: request interceptor

// Request interceptor. Each request carries a token in the request header
axios.interceptors.request.use((config) = > {
  if(localStorage.getItem('Authorization')) {
    config.headers.Authorization = localStorage.getItem('Authorization')}return config;
}, (error) = > {
  return Promise.reject(error);
})
Copy the code

401 UnauthorizedTo deal with

If the front end gets the 401 status code returned by the back end, the token information is cleared and the login page is redirected.

localStorage.removeItem('Authorization');
this.$router.push('/login');
Copy the code

Navigation guard 与 Request interceptor

The navigational guard simply determines whether a token value exists (regardless of whether the token is valid or not) and redirects if it does not/invalidates.

The request interceptor sends the request to the back end and verifies that if the token is valid, the access succeeds; otherwise, the access fails and the request is redirected.

⭐ In short, vue-Router navigational guards and AXIos interceptors are often used to make page permissions judgments!

FAQ

Q: Why not also send a request in the navigator to verify whether the token has expired, so that the user can be reminded to log in again when the token has expired? A: The token itself is used for interface authentication. After the token expires, data cannot be requested. In today’s single-page applications, there is no need to interact with the back end when accessing some pages, that is, there is no interface request. This has nothing to do with token interface authentication, so there is no need for verification. As long as it passes through the interceptor must be an interface request, so the interceptor is verified to be expired. The navigator validates, of course, but it would be a waste of ineffective resources to validate pages that do not interact.


πŸ™Žβ™‚οΈ blog quote:

  • Vue project to achieve user login and token verification
  • A step-by-step Vuex tutorial that a monkey could understand
  • Vue-router navigation guard vs. AXIos request interceptor