It's annoying to plug in a video.You can go out and turn right to Youku. Click on me!).
1. Backend Build1.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 "[email protected]"; 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:$`, "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" <$>`, 37 to: ko.email, 38 subject: "Wang Zirui's Blog Registration Verification Code", 39 html: `Authentication code is $,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:$`, 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:$`, "code"); const saveExpire = Store.hget(`nodemail:$`, "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. vuex,nuxtServerInit
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://$:$`, 73 badge: true 74 }); 75 } 76 77 start();