Cree una plataforma de compras sencilla desde cero (2)

Cree una plataforma de compras simple desde cero (1): https://blog.csdn.net/time_____/article/details/105191286
Código fuente del proyecto (actualización continua):
https://gitee.com/DieHunter/myCode/ El

artículo anterior sobre árbol / maestro / compras completó la construcción del cuerpo principal del proyecto y el módulo de complemento. El propósito de este artículo es construir la función de inicio de sesión y verificación del token del lado del servidor

Servidor:

Estructura del directorio de archivos

El archivo de entrada es server.js , simplemente configúrelo, déjelo ejecutar

const express = require("express");
const app = express();

app.listen(1024, () => {
  console.log("Server Start~");
});

Use el terminal para acceder al directorio server.js, ingrese el servidor de nodo para ejecutar el archivo de entrada y muestre Server Start ~ para indicar que el funcionamiento fue exitoso, y luego introduzca algunos módulos

const express = require("express");
const app = express();
const routes = require("./routes/routes");
const cors = require("cors"); //引入cors模块(解决跨域问题)
const path = require("path");
app.use(cors());
app.all("*", function (req, res, next) {
  //设置允许跨域的域名,*代表允许任意域名跨域
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "content-type"); //允许的header类型
  res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS"); //跨域允许的请求方式
  next(); //是否继续向下执行
});
let bodyParser = require("body-parser"); //post传输数据类型
app.use(
  bodyParser.urlencoded({
    extended: false,
  })
);
new routes(app);//初始化路由
app.use(bodyParser.json());
app.use("/public", express.static(path.join(__dirname, "./public")));//静态目录

app.listen(1024, () => {
  console.log("Server Start~");
});

Después de completar todas las configuraciones, continúe con el siguiente paso para configurar el enrutamiento y la verificación del token

Cree una nueva clase estática en el archivo utils.js e introduzca jwt (jsonwebtoken), cree una nueva clase estática de configuración en el archivo config.js para almacenar las variables de configuración (nombre de la interfaz, clave pública, constante), y también necesita usarlo Crypto realiza el cifrado y descifrado de datos, cifrado de sal de contraseña Bcrypt

utils.js

const jwt = require("jsonwebtoken");
const config = require("../config/config");
const cryptoJS = require("crypto-js");//用来加密解密前端参数
let { UserKey, AdminKey,CryptoKey} = config;//token加密关键字,秘钥
let key = cryptoJS.enc.Utf8.parse(CryptoKey);//生成16进制秘钥
module.exports = class Utils {
   static parseUrl(req, res) {//获取前端传递的参数
    return req.method == "POST" ? req.body : this.urlSplit(req.url);
  }
   static urlSplit(url) {//get获取的参数解析
    let list = url.split("?")[1].split("&");
    let leng = list.length;
    let obj = {};
    for (let i = 0; i < leng; i++) {
      let key = list[i].split("=")[0];
      let val = list[i].split("=")[1];
      obj[key] = val;
    }
    return obj;
  }
/*
   * @param {string} type 'user'||'admin'      用户类型
   * @param {string} user                      用户名  
   * @param {bool} rempsd                      是否记住密码
   */
  static createToken = (type, user, rempsd) => {//生成token,用户登录时调用
    let payload = {
      user: user,
    };
    return jwt.sign(payload, type == "admin" ? AdminKey : UserKey, {
      expiresIn: rempsd ? "3d" : "6h",
    });
  };
 /*
   * @param {object} req       前端请求对象
   * @param {object} res       服务端接收对象
   * @param {fn} next          中间件响应方法
   */
  static checkToken = (req, res, next) => {
    let _data = this.parseUrl(req, res); //解析前端参数
    if (_data.crypto) {
      _data = this.getCrypto(_data.crypto); //对前端参数解密
    }
    let isUser = true; //用户
    let isAdmin = true; //管理员
    let _decoded = ""; //加密的用户名
    jwt.verify(_data.token, UserKey, function (err, decoded) {
      if (err) {
        isUser = false;
      } else {
        _decoded = decoded;
      }
    });
    jwt.verify(_data.token, AdminKey, function (err, decoded) {
      if (err) {
        isAdmin = false;
      } else {
        _decoded = decoded;
      }
    });
    if (isUser || isAdmin) {
      _data.id = _decoded;
      _data.userTokenType = isAdmin ? "admin" : "user";
      res._data = _data;
      next(); //中间件响应
    } else {
      res.send({
        result: -999,
        msg: "登录超时,请重新登录",
      });
    }
  };
/* Crypto加密方法
   * @param {object} _data       对用户请求后端的参数进行加密
   */
  static setCrypto(_data) {
    let encrypted = cryptoJS.AES.encrypt(JSON.stringify(_data), key, {
      mode: cryptoJS.mode.ECB,
      padding: cryptoJS.pad.Pkcs7,
    });
    return encrypted.toString();
  }
 /* Crypto解密方法
   * @param {string} _token       将秘文解密成对象形式
   */
  static getCrypto(_token) {
    _token = decodeURIComponent(_token); //前端传参有特殊字符(中文)时转义(替换百分号)
    let decrypt = cryptoJS.AES.decrypt(_token, key, {
      mode: cryptoJS.mode.ECB,
      padding: cryptoJS.pad.Pkcs7,
    });
    return JSON.parse(cryptoJS.enc.Utf8.stringify(decrypt).toString());
  }
  static createBcrypt(password) {//加密密码
    return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
  }
  static checkBcrypt(_password, _hash) {//对比密码
    return bcrypt.compareSync(_password, _hash);
  }
}

Después de configurar las utils, configure el enrutamiento, cree un nuevo archivo route.js en la carpeta de rutas y use el token para verificar que el usuario sea correcto

const Util = require("../utils/utils");
const Config = require("../config/config");
module.exports = class Route {
  constructor(app) {
    app.get(Config.ServerApi.checkToken, Util.checkToken, (req, res) => {
      res.send({
        result: 1,
        msg: "验证成功",
        data: res._data
      });
    });
  }
};

Configurar config.js

module.exports = {
  Agreement: "http://",//协议
  DataBaseUrl: "127.0.0.1",//ip或域名
  DataBasePort: ":27017",//数据库端口
  DataBaseName: "shopping",//数据库文档名称
  ServerUrl: "",
  ServerPort: ":1024",//服务端请求端口
  Path: "/",//路由名
  UserKey: "user",//用户token加密标识
  AdminKey: "admin",//管理员token加密标识
  CryptoKey: "tokenkey",//Crypto加密关键字,用于生成16进制秘钥
  ServerApi: {//接口名称
    checkToken: "/checkToken",//token验证
    userLogin: "/userLogin",//用户登录
  }
}

Posteriormente, cree una nueva interfaz de enrutamiento de administración de usuarios , pero antes de eso, necesitamos configurar la base de datos

  1. Descargue Robo3t e instálelo
  2. Cree una nueva base de datos, aquí el nombre de mi nueva base de datos es Shopping
  3. Cree una nueva tabla de base de datos, aquí estoy creando una tabla de usuarios

Conectarse a la base de datos

  1. Cree una nueva conexión de base de datos en model.js (modo de observador principal, similar a los eventos personalizados de monitoreo de sockets)
    const mongoose = require('mongoose');
    const config = require('../../config/config')
    module.exports = class Mongoose {
        constructor() {
            mongoose.connect(`mongodb://${config.DataBaseUrl+config.DataBasePort+config.Path+config.DataBaseName}`, {
                useNewUrlParser: true
            });
            this.db = mongoose.connection;
            this.db.on("error", function (error) {
                console.log("Err:" + error);
            });
    
            this.db.on("open", function () {
                console.log("Connet Success~");
            });
    
            this.db.on('disconnected', function () {
                console.log('Connet Stop~');
            });
            return mongoose
        }
    }

     

  2. El nuevo esquema de la base de datos se utiliza para conectarse a la tabla de datos , aquí eliminamos directamente los elementos de configuración al archivo config.js

    const _mongoose = require('./model');
    let mongoose = new _mongoose()
    const _schema = mongoose.Schema;
    module.exports = class Schema {
        constructor(config) {
            let schema = new _schema(config.data);
            let Model = mongoose.model(config.modelName, schema); //新建数据库
            return Model
        }
    }

     

  3. Nueva configuración de campo predeterminada de la tabla de usuario en config.js

    Collections: {
        Users: {
          modelName: "users",
          data: {
            headPic: {//头像
              type: String,
              required: false,
              default: "public/assets/img/default.gif"
            },
            userType: {//用户类型(管理员/用户)
              type: String,
              required: true,
            },
            username: {//用户名
              type: String,
              required: true,
            },
            password: {//密码
              type: String,
              required: true
            },
            sex: {//性别
              type: String,
              required: true
            },
            mailaddress: {//邮箱地址
              type: String,
              required: true
            },
            mailurl: {//邮箱类型
              type: String,
              required: true
            },
            alladdress: {//省市县
              type: Array,
              required: false,
              default: []
            },
            address: {//具体地址
              type: String,
              required: false,
              default: ''
            },
            descript: {//个人说明
              type: String,
              required: false,
              default: ''
            },
            time: {//注册时间
              type: String,
              required: true
            },
            isactive: {//是否冻结用户
              type: Boolean,
              default: true
            }
          }
        }
      },

     

Lo anterior es el código de back-end para la configuración, la verificación del token y el inicio de sesión 

para resumir

Es necesario construir el proyecto en una idea de diseño similar a MVC La separación del modelo de datos y la capa de control puede hacer que el código sea claro, reutilizable y mantenible.

Supongo que te gusta

Origin blog.csdn.net/time_____/article/details/105408640
Recomendado
Clasificación