Bs part

Last time too much nonsense, it is estimated that some partners did not see too clearly. It will be much leaner this time. Only mention the key points.

Individuals belong to the front end, the back end to see the mercy. I hope this article will help

Project Address:

Front end: https://github.com/ht-sauce/dream

The backend: https://github.com/ht-sauce/dream-admin

I. Authentication and selection

There’s not much to say about this, but basically baidu’s result is JWT

Eggjs is officially egg-JWT, which is essentially jsonWebToken

An egg – JWT address: https://www.npmjs.com/package/egg-jwt

Jsonwebtoken address: https://www.npmjs.com/package/jsonwebtoken

I won’t go into details about the plug-in configuration of EggJS. Too easy (compliments eggJS again).

Write to the login interface first to ensure that authentication information is generated

1, put the complete login interface function first

// Login interface asynclogin() { const { ctx, service } = this; const userBusiness = service.consumer.user; const query = ctx.request.body; Const rule = {account: {const rule = {account: {type: 'string', required: true}, // message message password: {type: 'string', required: true}}; try { await ctx.validate(rule, query); // Whether the user has const login = await userbusiness.userlogin (query);if(login) {// Generate password after login, valid for 24 hours const token = ctx.helper.generate_token(query.account); Const userInfo = {userInfo: await userbusiness.find (query), sign: token,}; ctx.body = ctx.helper.result(userInfo); }else {
      ctx.body = ctx.helper.result(' ', 1,'User does not exist please register');
    }
  } catch (e) {
    ctx.body = ctx.helper.result(' ', -1, e); }}Copy the code

2. Principle analysis

The main thing is to determine the user name and password first, and then generate the password using a self-encapsulated helper (an extension of EggJS).

In the case of a helper, there is a unified encapsulation of functions.

And then throw it all to the front end.

3. Middleware parses passwords for verification and interception

1. Middleware code

'use strict';

module.exports = (options, app) => {
  return async function(ctx, next) {
    const token = ctx.request.header.authorization;

    try {
      if(token) {// Verify current token const decode = app.jwt.verify(token, options.secret); // Verify that user information is normalif(! decode || ! decode.account) { ctx.body = ctx.helper.result(' ', 1,'User information missing', 1); } / / verify the user whether there is a const user = await CTX. Model. Consumer. User. FindOne ({where: { account: decode.account } }
        );
        if(user) {// If the password validity period is less than 15 minutes, the new password is sent to the front-endif (decode.exp - Date.now() / 1000 < 60 * 15) {
            const token = ctx.helper.generate_token(decode.account);
            ctx.set('Authorization', token); } // After all validation has passed, we can access await next() normally; }else {
          ctx.body = ctx.helper.result(' ', 1,'User information verification failed', 1); }}else {
        ctx.body = ctx.helper.result(' ', 1,'Password verification failed', 1);
      }
    } catch (e) {
      console.log(e);
      ctx.body = ctx.helper.result(' ', -1, e, 1); }}; };Copy the code

2. Principle analysis

Look at the code carefully. After various validations only the await next () part is the final correct code to execute. There is no problem with representation authentication.

From the front end, it’s just if else passed.

3. Password refresh problem

The code above has one section

// If the validity period of the password is less than 15 minutes, the new password is sent to the front-endif (decode.exp - Date.now() / 1000 < 60 * 15) {
            const token = ctx.helper.generate_token(decode.account);
            ctx.set('Authorization', token);
          }Copy the code

The key here is to realize that when the user does not stop operation can not suddenly log out because the password expires. Therefore, you need to verify the expiration time of the password. Send a new password to the front end when it is about to expire. Have the front end refresh the current cached password. Be careful not to be too short. Fifteen minutes is a reasonable amount of time.

4. Some back-end interfaces pass directly without verifying passwords.

This is basically nothing to worry about in back-office projects. But an open blog is necessary. This is mainly to see the official processing of eggJS middleware.

Address: https://eggjs.org/zh-cn/basics/middleware.html

I personally do the same

// Config. Middleware = ['jwtAuthorize']; // Config. jwtAuthorize = {secret:'daihaitian19940329'// Ignore: ['${config.dreamCustom.prefix}/noauth` ],
};Copy the code

Third, front-end storage password and password sending problems

1. Login interface

The login part is simple, just cache the user information. The main core lies in where ajax functions are encapsulated

/ / loginlogin() {
  let data = {
    account: this.logindata.userName,
    password: userLoginPassword(this.logindata.password)
  };
  this.logining = true;
  this.axios
    .ajax({
      url: this.$api.consumer().user.login,
      data: data,
      method: "post"
    })
    .then(e => {
      this.logining = false; // Store user data to cache store.clearall (); store.set("user_info", e.data);
      console.log(e.data);
    })
    .catch(e => {
      this.logining = false;
      console.log(e);
    });Copy the code

Encapsulate Ajax functions and handle passwords and password refreshes globally

The code releases the core wrapper

1, a HEADERS encapsulation. The password needs to be sent to the back end when there is password data on the front end

// Authorize functions wrap const authorize = herders => {const user_info = store.get("user_info");
  if (user_info && user_info.sign) {
    herders.Authorization = user_info.sign;
    return herders;
  } else {
    returnherders; }};Copy the code

2. Encapsulation of password refresh function

After a series of validations, you need to refresh the password if a password is generated in the headers returned by the backend

Refresh_sign_or_out (res) {console.log(res);if(! res || ! res.data) { this.logout();return false; } / /typeIf the type is 1, you must log outif (res.data.type === 1) {
    this.logout();
    return false;
  }
  if (res.headers.authorization) {
    const user_info = store.get("user_info");
    user_info.sign = res.headers.authorization;
    store.set("user_info", user_info);
  }
  return true;
}Copy the code

Review of defects

1. The biggest drawback is that as long as the password is generated, it can be verified.

2. If the previous problem is solved and the password is unique, then it is necessary to solve the concurrent password update to ensure that the subsequent interface will not report errors due to password refresh

3. Password uniqueness

Personal: No. At present, this can guarantee the concurrency problem, as long as the password is not unique, then do not worry about the above problems. And personally belong to the front end, not going to delve into it.