从零开始,搭建一个简单的购物平台二

从零开始,搭建一个简单的购物平台(一):https://blog.csdn.net/time_____/article/details/105191286
项目源码(持续更新):
https://gitee.com/DieHunter/myCode/tree/master/shopping

上一篇文章将项目主体以及插件模块搭建完成,这篇文章目的主要搭建服务端token验证及登录功能

服务端:

文件目录结构

入口文件为server.js,简单配置一下,先让他能运行起来

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

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

使用终端cd到server.js目录,输入node server运行入口文件,显示Server Start~表示运行成功,之后引入一些模块

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~");
});

全部设置完之后进行下一步,配置路由与token验证

在utils.js文件中新建一个静态类,并且引入jwt(jsonwebtoken),在config.js文件中新建config静态类用于存放配置变量(接口名,公钥秘钥,常量),此外还需用到crypto进行数据加解密,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,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,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,});
    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);
  }
}

配置完成utils后进行路由配置,在routes文件夹下新建routes.js文件,并使用token验证用户是否正确

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
      });
    });
  }
};

配置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",//用户登录
  }
}

随后,新建用户管理路由接口,但是在此之前,我们需要配置一下数据库

  1. 下载Robo3t,并安装
  2. 新建数据库,这里我新建的数据库名称是Shopping
  3. 新建数据库表,这里我新建的是users表

连接数据库

  1. 在model.js中新建数据库连接(原理观察者模式,类似与socket监听自定义事件)
    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. 新建数据库Schema用于连接数据表,这里我们直接将配置项剥离到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. 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,password: {//密码
              type: String,required: true
            },sex: {//性别
              type: String,mailaddress: {//邮箱地址
              type: String,mailurl: {//邮箱类型
              type: String,alladdress: {//省市县
              type: Array,default: []
            },address: {//具体地址
              type: String,default: ''
            },descript: {//个人说明
              type: String,time: {//注册时间
              type: String,isactive: {//是否冻结用户
              type: Boolean,default: true
            }
          }
        }
      },

     

以上是配置,token验证及登录的后端代码 

总结

将项目搭建成类似于mvc的设计思想很有必要,数据模型和控制层的剥离,可以使代码思路清晰,复用性以及可维护性提升

原文地址:https://blog.csdn.net/time_____

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于nodejs...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs怎么实现目录不存在自动创建”文章能帮助大...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs如何实现定时删除文件”文章能帮助大家解决疑惑...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文...
本篇内容主要讲解“怎么安装Node.js的旧版本”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎...
这篇“node中的Express框架怎么安装使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要介绍“nodejs如何实现搜索引擎”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs如何实现搜索引擎...
这篇文章主要介绍“nodejs中间层如何设置”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs中间层如何设置”文...
这篇文章主要介绍“nodejs多线程怎么实现”,在日常操作中,相信很多人在nodejs多线程怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
这篇文章主要讲解了“nodejs怎么分布式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs怎么分布式”...
本篇内容介绍了“nodejs字符串怎么转换为数组”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
这篇文章主要介绍了nodejs如何运行在php服务器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇nodejs如何运行在php服务器文章都...
本篇内容主要讲解“nodejs单线程如何处理事件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“nodejs单线程如何...
这篇文章主要介绍“nodejs怎么安装ws模块”,在日常操作中,相信很多人在nodejs怎么安装ws模块问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
本篇内容介绍了“怎么打包nodejs代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!
本文小编为大家详细介绍“nodejs接收到的汉字乱码怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs接收到的汉字乱码怎么解决”文章能帮助大家解...
这篇“nodejs怎么同步删除文件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇...
今天小编给大家分享一下nodejs怎么设置淘宝镜像的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希