vue koa2 mongodb does the back-end part of the personal blog login registration function from scratch

0. Effect demonstration

It's annoying to plug in a video.You can go out and turn right to Youku. Click on me!).  

1. Backend Build

1.1 Project Structure

First look at the server directory on the back end

Explain one by one

  • First, the dbs folder, as its name implies, operates on the database, and modules is the mongoose model that operates on the database.
  • config.js is designed to make it easy to modify database data.
  • Interface is the interface folder, utils is the tool's meaning, axios needed for the interface and account centralized passports are all modified here (what passports are?).
  • At the same level as utils, users.js is the route to the user interface, and the logic is in this file
  • index.js and dbs, interface folder siblings.Is the entry file for the entire server directory.

 

1.2 Backend Configuration

First, take a look at config.js and put your code directly.

 1 // Export the corresponding configuration, and then you can easily use the data below, if you change it, it will be more convenient to modify.
 2 export default {
 3   //dbs Represents a server that needs to be connected
 4   dbs: "mongodb://127.0.0.1:27017/myblog2",
 5   //redis The object is to provide redis Information
 6   redis: {
 7     get host() {
 8       return "127.0.0.1";
 9     },
10     get port() {
11       return 6379;
12     }
13   },
14   // smtp Object uses mailbox to send authentication codes
15     smtp: {
16     get host() {
17       return "stmp.qq.com";
18     },
19     get user() {
20       return "470557449@qq.com";
21     },
22     // this pass Code is qq Mailbox provided.Here's what random shots are not true.
23     get pass() {
24       return "pfpeqwddadadasdaf";
25     },
26     // Make a random verification code
27     get code() {
28       return () => {
29         return Math.random()
30           .toString(16)
31           .slice(2, 6)
32           .toUpperCase();
33       };
34     },
35     // Create a time, which is when you send your mailbox.
36     get expire() {
37       return () => {
38         return new Date().getTime() + 60 * 60 * 1000;
39       };
40     }
41   }
42 };

For the smtp protocol, you can use it to send authentication codes.How to get pass code for qq mailbox?

_Open mailbox click settings first:

_Click the account button of navbar above

_Slide down to find the smtp option

 

1.3 Creating a data model

There are too many paving things, I suggest you come back after you have learned them.

1. mongodb and mongoose do not go into detail. mongodb can refer to the introductory tutorial I wrote earlier. Click on me!)

2. The general process of mongoose is to introduce, create shcema, create model.Then proceed with the operation.Details go to the official website ( Click on me! ).For this order, we won't introduce it first. It's in index.js. Now let's start with the section Creating schema and creating model.

3. With some async await and syntax for deconstructing assignments, if you don't understand it and can jump to learn the new version of js automatically, recommend Ruan Yifeng's " ECMAScript 6 Introduction Tutorial (Call book names directly!)

 

Say nothing more, just put the code:

 1 // server/dbs/modules/user.js
 2 // Import Monogoose
 3 import mongoose from "mongoose";
 4 // Establish schema
 5 const Schema = mongoose.Schema;
 6 // Establish userSchema
 7 const UserSchema = new Schema({
 8   username: {
 9     type: String,
10     unique: true,
11     require: true
12   },
13   password: {
14     type: String,
15     require: true
16   },
17   email: {
18     type: String,
19     require: true
20   }
21 });
22 // export user Model
23 export default mongoose.model("User", UserSchema);

Now login registration needs to be stored in the library, only these are needed, and the cached data for authentication is stored uniformly in redis.The logic of reids is unified in the interface of users.

 

1.4 Create user interface

Maybe you didn't notice that I wasn't talking about utils, axios and passport.js.Because it's not time.

Now configure the user interface, put up a shelf, and then talk about logic

// koa-router Must be quoted, not explained
import Router from "koa-router";
// Send Authentication Code redis,Because there may be a large demand. redis Higher efficiency
import Redis from "koa-redis";
// use nodeMailer Plug-in to send mail.
import nodeMailer from "nodemailer";
// USer Model, to operate on mongodb
import User from "../dbs/modules/users";
// Configuration parameters for sending mail
import Email from "../dbs/config";
// axios To request data
import axios from "./utils/axios";
//To introduce passprot middleware
import Passport from "./utils/passport";

// Create a route that he starts with/users
let router = new Router({ prefix: "/users" });

// Create a redis Warehouse of.
let Store = new Redis().client;

// export router
export default router;

The logic of redis is to introduce the koa-redis plug-in and create a new store object.We then operate on the store object.Please go to npm for details ( Click on me!)

 

1.4.1 Register Authentication Code Interface

First, the first task is to register. The logic of registration is to fill in the mailbox and user name, determine the password, and then send a verification code mail to verify.

Then the first configuration is the route to send the authentication code, because they are all linear code, so put the code directly, as follows:

 1 // Send Authentication Code
 2 router.post("/verify", async ctx => {
 3   //Obtain username
 4   let username = ctx.request.body.username;
 5 
 6   //Can not look at 6-16 Yes, come back when you see the end.
 7   //The valid time to get the verification code
 8   const saveExpire = await Store.hget(`nodemail:${username}`, "expire");
 9   //If the validity time of the verification code is too short, it cannot be sent again.
10   if (saveExpire && new Date().getTime() - saveExpire < 0) {
11     ctx.body = {
12       code: -1,
13       msg: "Verification requests are too frequent, once in a minute"
14     };
15     return false;
16   }
17   //Then use nodeMailer Create a transport
18   let transporter = nodeMailer.createTransport({
19     // server Name
20     service: "qq",
21     // user And his pass
22     auth: {
23       user: Email.smtp.user,
24       pass: Email.smtp.pass
25     }
26   });
27   //Get the authentication code and time, as well as the mailbox and user name entered by the user
28   let ko = {
29     code: Email.smtp.code(),
30     expire: Email.smtp.expire(),
31     email: ctx.request.body.email,
32     user: ctx.request.body.username
33   };
34   // Mail profile
35   let mailOptions = {
36     from: `" Blog Registration Certification Mail" <${Email.smtp.user}>`,
37     to: ko.email,
38     subject: "Wang Zirui's Blog Registration Verification Code",
39     html: `Authentication code is ${ko.code},Please complete registration as soon as possible!`
40   };
41   await transporter.sendMail(mailOptions, (error, info) => {
42     if (error) {
43       return console.log(error);
44     } else {
45       // When the message is sent successfully, save the data and use it later.
46       Store.hmset(
47         `nodemail:${ko.user}`,
48         "code",
49         ko.code,
50         "expire",
51         ko.expire,
52         "email",
53         ko.email
54       );
55     }
56   });
57   ctx.body = {
58     code: 0,
59     msg: "Authentication code sent, possibly delayed, valid for 1 minute"
60   };
61 });

 

1.4.2 Registration Interface

After the verification code is issued, we can proceed with the registration.

Place the code directly as well, which is easy to understand.

router.post("/signup", async ctx => {
  // Get the information in the form first,Write like this es6 Deconstructive Assignment Grammar
  const { username, password, email, code } = ctx.request.body;
  if (code) {
    const saveCode = Store.hget(`nodemail:${username}`, "code");
    const saveExpire = Store.hget(`nodemail:${username}`, "expire");

    if (saveCode == code) {
      if (new Date().getTime() - saveExpire > 0) {
        ctx.body = {
          code: -1,
          msg: "Verification code has expired, please try again"
        };
        return false;
      }
    } else {
      ctx.body = {
        code: -1,
        msg: "Please fill in the correct verification code"
      };
    }
  } else {
    ctx.body = {
      code: -1,
      msg: "No verification code entered"
    };
  }
let user
= await User.find({ username }); if (user.length) { ctx.body = { code: -1, msg: "Already registered" }; return; } let nuser = await User.create({ username, password, email }); console.log(nuser); if (nuser) { ctx.body = { code: 0, msg: "login was successful" }; } else { ctx.body = { code: -1, msg: "login has failed" }; } });

 

 

1.4.3 Logon Interface

Passport is involved here because the status of the login needs to be centrally managed, so Passport is a plug-in.If you need to get started quickly, you can read this short book. Click on me!)

I'm just telling the truth here.Not to mention, you can refer to the above brief book plus my code to understand it for yourself.

 1 // server/interface/utils/passport.js
 2 // Introduce passprot ,Then a local strategy is introduced to verify that the user is valid, and finally an operational model is introduced.
 3 import passport from "koa-passport";
 4 import LocalStrategy from "passport-local";
 5 import UserModel from "../../dbs/modules/users";
 6 
 7 // passport Load the policy middleware and create a new one location Object inside for user identification.
 8 passport.use(
 9   //Create a new policy, then the three parameters are username password and callback
10   new LocalStrategy(async function(username, password, done) {
11     //Use here where Is the parameter an object when representing a search
12     let where = {
13       username
14     };
15     // use user Of Mongoose Model to search for user Records in a database, using res To receive
16     const res = await UserModel.findOne(where);
17     // judge res Is there, there is no callback function to use policy done Returns an error message that does not exist for the user.
18     if (res != null) {
19       // If the Password And input password Analog, return one res
20       if (res.password === password) {
21         return done(null, res);
22       } else {
23         // A password error is returned if it does not match.
24         return done(null, false, "Password error");
25       }
26     } else {
27       return done(null, false, "user does not exist");
28     }
29   })
30 );
31 
32 // Serialization and deserialization, nothing serious.
33 passport.serializeUser(function(user, done) {
34   done(null, user);
35 });
36 
37 passport.deserializeUser(function(user, done) {
38   return done(null, user);
39 });
40 
41 // export passport Centralized control middleware.
42 export default passport;

 

Place the code in the user.js interface again

 1 router.post("/signin", async (ctx, next) => {
 2   return Passport.authenticate("local", (err, user, info, status) => {
 3     if (err) {
 4       ctx.body = {
 5         code: -1,
 6         msg: err
 7       };
 8     } else {
 9       if (user) {
10         ctx.body = {
11           code: 0,
12           msg: "Login Successful",
13           user
14         };
15         return ctx.login(user);
16       } else {
17         ctx.body = {
18           code: 1,
19           msg: info
20         };
21       }
22     }
23   })(ctx, next);
24 });

 

There may be doubts here about how my interface return ed the passport object without getting username and password data from ctx.

The problem is that the koa2 object must use the bodyParser's Middleware in index.js.The code is as follows:

 // bodyParser In extendTypes Must add, otherwise passport Can't resolve username and passport
  app.use(
    bodyParser({
      extendTypes: ["json", "form", "text"]
    })
  );

 

You can then resolve to the username and passport that you logged in to.

 

1.4.4 Exit and Query User Interface

Place code directly, no difficulty

 1 router.get("/getUser", async ctx => {
 2   if (ctx.isAuthenticated()) {
 3     const { username, email } = ctx.session.passport.user;
 4     ctx.body = {
 5       user: username,
 6       email
 7     };
 8   } else {
 9     ctx.body = {
10       user: "",
11       email: ""
12     };
13   }
14 });

 

Log out

 1 router.get("/exit", async (ctx, next) => {
 2   await ctx.logout();
 3   if (!ctx.isAuthenticated()) {
 4     ctx.body = {
 5       code: 0
 6     };
 7   } else {
 8     ctx.body = {
 9       code: -1
10     };
11   }
12 });

 

There is a second way to get user data if you want to, from session, what is session?Everyone has their own Baidu, which is simply a cookie on the server side.

Then use vuex with nuxtServerInit method of nuxt.js.This again requires understanding vuex and nuxtServerInit, which is linked. vuexnuxtServerInit

Project structure

 

 

If you use vue-cli, there will be modules folders for the model, but nuxt.js will be placed directly flat, refer to the nuxt.js documentation for details.( Click on me!)

 

Place the code directly, too.

 1 //store/user.js
 2 const state = () => ({
 3   user: ""
 4 });
 5 const mutations = {
 6   setUser(state, param) {
 7     state.user = param;
 8   }
 9 };
10 const actions = {
11   setUser: ({ commit }, param) => {
12     commit("setUser", param);
13   }
14 };
15 
16 export default { state, mutations, actions };
 1 //store/index.js
 2 const actions = {
 3   async nuxtServerInit({ commit }, { req }) {
 4     if (req.user) {
 5       commit("user/setUser", req.user.username);
 6     }
 7   }
 8 };
 9 
10 export { actions };

 

Then we can call $store.state.user.user anywhere on the page to get the user name.Asynchronous fetching can be omitted.

 

1.5 index.js file

Place the code directly, as explained earlier, this is a boot backend file

 1 // server/index.js
 2 const Koa = require("koa");
 3 const consola = require("consola");
 4 const { Nuxt, Builder } = require("nuxt");
 5 
 6 import bodyParser from "koa-bodyparser"; // This was added at the beginning, but it couldn't be resolved without adding a word. request.body. post The request is for nothing.
 7 import json from "koa-json";
 8 import mongoose from "mongoose";
 9 import dbConfig from "./dbs/config";
10 import Redis from "koa-redis";
11 import session from "koa-generic-session";
12 import users from "./interface/users";
13 import passport from "./interface/utils/passport";
14 
15 const app = new Koa();
16 
17 // Import and Set Nuxt.js options
18 const config = require("../nuxt.config.js");
19 config.dev = app.env !== "production";
20 
21 async function start() {
22   // Instantiate nuxt.js
23   const nuxt = new Nuxt(config);
24 
25   const {
26     host = process.env.HOST || "127.0.0.1",
27     port = process.env.PORT || 3000
28   } = nuxt.options.server;
29 
30   //This is for encryption
31   app.keys = ["my", "keyskeys"];
32   //Whether to set up proxy
33   app.proxy = true;
34   //session Prefix
35   app.use(session({ key: "my", prefix: "my:uid", store: new Redis() }));
36   //mongoose link Mongodb
37   mongoose.connect(dbConfig.dbs, {
38     useNewUrlParser: true
39   });
40   //Initialization passport
41   app.use(passport.initialize());
42   //Give Way passport Use session
43   app.use(passport.session());
44 
45   // Build in development
46   if (config.dev) {
47     const builder = new Builder(nuxt);
48     await builder.build();
49   } else {
50     await nuxt.ready();
51   }
52   //analysis json Middleware for use
53   app.use(json());
54   // bodyParser In extendTypes Must add, otherwise passport Can't resolve username and passport
55   app.use(
56     bodyParser({
57       extendTypes: ["json", "form", "text"]
58     })
59   );
60   // Loading Routing Middleware
61   app.use(users.routes()).use(users.allowedMethods());
62 
63   app.use(ctx => {
64     ctx.status = 200;
65     ctx.respond = false; // Bypass Koa's built-in response handling
66     ctx.req.ctx = ctx; // This might be useful later on, e.g. in nuxtServerInit or with nuxt-stash
67     nuxt.render(ctx.req, ctx.res);
68   });
69 
70   app.listen(port, host);
71   consola.ready({
72     message: `Server listening on http://${host}:${port}`,
73     badge: true
74   });
75 }
76 
77 start();

Tags: Javascript Redis Mongoose Session JSON

Posted on Sat, 18 Jan 2020 12:49:51 -0500 by kris81