preface

JWT(JSON Web Token) is an open jSON-based standard (RFC 7519) implemented for passing declarations between network environments.

More introduction and explanation, as well as various principles, I will not elaborate here. JWT is not new, and there are already a lot of online references. Not very understanding can search relevant information on the Internet.

The source code

Talk is cheap. Show me the code.

The working process

JWT is essentially a token. Authentication is performed when the HTTP connection is made at the front and back ends.

  1. The blog background management system initiates the login request, and after the verification of the backend server is successful, JWT authentication information is generated.
  2. The front end stores JWT after receiving it;
  3. When each subsequent HTTP request is initiated by the interface invocation, the front-end will send the JWT to the backend together with authorization in the HEADERS parameter of HTTP.
  4. When receiving the request, the backend will verify whether the user who initiated the HTTP request has access permission according to the information in JWT. If the user has access permission, the server will continue processing, and if not, the 401 error will be returned directly.

The implementation process

1. JWT is generated successfully

Note: The following code only retains the core code, the detailed code can be viewed in the corresponding file, the same as below.

// /server/api/admin/admin.controller.js
const jwt = require('jsonwebtoken');
const config = require('.. /.. /config/config');

exports.login = async(ctx) => {
  // ...
  if (hashedPassword === hashPassword) {
    // ...
    / / the user token
    const userToken = {
      name: userName,
      id: results[0].id
    };
    / / issue a token
    const token = jwt.sign(userToken, config.tokenSecret, { expiresIn: '2h' });
    // ...
  }
  // ...
}
Copy the code

2. Add the middleware verification JWT

// /server/middlreware/tokenError.js
const jwt = require('jsonwebtoken');
const config = require('.. /config/config');
const util = require('util');
const verify = util.promisify(jwt.verify);

/** * Check whether the token is available */
module.exports = function () {
  return async function (ctx, next) {
    try {
      / / for JWT
      const token = ctx.header.authorization; 
      if (token) {
        try {
          // Decrypts the payload to obtain the user name and ID
          let payload = await verify(token.split(' ') [1], config.tokenSecret);
          ctx.user = {
            name: payload.name,
            id: payload.id
          };
        } catch (err) {
          console.log('token verify fail: ', err)
        }
      }
      await next();
    } catch (err) {
      if (err.status === 401) {
        ctx.status = 401;
        ctx.body = {
          success: 0.message: 'Authentication failed'
        };
      } else {
        err.status = 404;
        ctx.body = {
          success: 0.message: '404'}; }}}}Copy the code

3. Add JWT processing to koa.js

You need to filter out the login interface during development; otherwise, JWT authentication will fail forever.

// /server/config/koa.js
const jwt = require('koa-jwt');
const tokenError = require('.. /middlreware/tokenError');
// ...

const app = new Koa();

app.use(tokenError());
app.use(bodyParser());
app.use(koaJson());
app.use(resource(path.join(config.root, config.appPath)));

app.use(jwt({
  secret: config.tokenSecret
}).unless({
  path: [/^\/backapi\/admin\/login/, /^\/blogapi\/ /]
}));

module.exports = app;

Copy the code

4. Front-end processing

Vue.js is used for front-end development and AXIos is used for sending HTTP requests.

  1. After successful login, store JWT in localStorage (can be stored according to personal needs, I personally prefer to store in localStorage).

    methods: {
        login: async function () {
          // ...
    
          let res = await api.login(this.userName, this.password);
          if (res.success === 1) {
            this.errMsg = ' ';
            localStorage.setItem('DON_BLOG_TOKEN', res.token);
            this.$router.push({ path: '/postlist' });
          } else {
            this.errMsg = res.message; }}}Copy the code

  2. Vue. Js verifies whether JWT exists before switching to the router. If not, the login page is redirected.

    // /src/router/index.js
    router.beforeEach((to, from, next) = > {
      if (to.meta.requireAuth) {
        const token = localStorage.getItem('DON_BLOG_TOKEN');
        if(token && token ! = ='null') {
          next();
        } else {
          next('/login'); }}else{ next(); }});Copy the code

  3. Add uniform Authorization information to HTTP in the AXIOS interceptor

    // /src/fetch/fetch.js
    axios.interceptors.request.use(
      config= > {
        const token = localStorage.getItem('DON_BLOG_TOKEN');
        if (token) {
          // Bearer is a confirmed header of JWT
          config.headers.common['Authorization'] = 'Bearer ' + token;
        }
        return config;
      },
      error => {
        return Promise.reject(error); });Copy the code

  4. The AXIos interceptor uniformly handles the return status when it receives an HTTP return

    // /src/main.js
    axios.interceptors.response.use(
      response= > {
        return response;
      },
      error => {
        if (error.response.status === 401) {
          Vue.prototype.$msgBox.showMsgBox({
            title: 'Error message'.content: 'Your login information is invalid, please log in again'.isShowCancelBtn: false
          }).then((val) = > {
            router.push('/login');
          }).catch((a)= > {
            console.log('cancel');
          });
        } else {
          Vue.prototype.$message.showMessage({
            type: 'error'.content: 'System error'
          });
        }
        return Promise.reject(error); });Copy the code

conclusion

This is the end of the process. Of course, JWT alone is not meant to be absolutely secure, but it is enough to authenticate a personal blogging system.

A little commercial at the end. Currently under development of the new version of personal blog, including front-end and back-end two parts, have been open source on GitHub, currently in the gradual improvement of the function. Welcome to fork and Star who are interested.