express+mongodb+react+typescript+antd搭建管理後臺系統(後端+前端)(上)

express+mongodb搭建具備用戶註冊、登陸、驗證等功能的後端

  • 安裝node

安裝node的教程上網一大把,這裏就不細說了,建議使用nvm安裝,能夠隨時切換node版本。node

  • 安裝mongodb

在這裏使用Homebrew安裝mongodb,首先更新Homebrew:git

brew update

mongodb提供3種版本供安裝:普通版、支持TLS/SSL版本和開發版,具體請參見mongodb官網。普通版本安裝執行如下指令:es6

brew install mongodb

從終端信息得知,無論安裝的是哪一種版本,都會安裝依賴openssl。
各個部分默認的安裝路徑是:github

The databases are stored in the /usr/local/var/mongodb/ directory
The mongod.conf file is here: /usr/local/etc/mongod.conf
The mongo logs can be found at /usr/local/var/log/mongodb/
The mongo binaries are here: /usr/local/Cellar/mongodb/[version]/binmongodb

一、配置數據庫:
首先建立保存數據的文件夾:shell

sudo mkdir -p /data/db

而後給剛建立的文件夾寫入數據權限:數據庫

sudo chown -R $USER /data/db

R是recursive遞歸的意思
若是想直接配置mongod.conf:express

nano /usr/local/etc/mongod.conf

能夠看到mongod.conf內容以下:npm

systemLog:
destination: file
path: /usr/local/var/log/mongodb/mongo.log
logAppend: true
storage:
dbPath: /usr/local/var/mongodb
net:
bindIp: 127.0.0.1

注意:若是準備鏈接非本機環境的mongodb數據庫,bind_ip = 0.0.0.0,而且經過homebrew安裝的mongodb不須要配置環境變量了,直接運行命令就行!json

二、啓動mongod服務:

mongod

使用此命令啓動mongod會發現輸出信息以下:

2016-06-13T10:25:09.929+0800 I CONTROL [initandlisten] MongoDB starting : pid=5693 port=27017 dbpath=/data/db 64-bit host=MacBookPro
......

能夠看到,會使用默認的數據保存路徑/data/db。但是/usr/local/etc/mongod.conf這個配置文件中的默認dbpath不是/usr/local/var/mongodb嗎?難道說配置文件沒有生效?
沒錯,以上啓動命令並不會讀取/usr/local/etc/mongod.conf。這是由於不經過$ mongod --config xxx.conf這種形式指定配置文件xxx.conf時mongodb會使用程序內置的默認配置,該配置對應的數據保存路徑爲/data/db。建議啓動mongod時經過--config參數指定配置文件,更多參考官網Configuration File Options。
因此,若是咱們配置了/usr/local/etc/mongod.conf並但願mongdb使用咱們的配置,可選的命令有2種:(1)$ mongod --config /usr/local/etc/mongod.conf和(2)$ mongod --config /usr/local/etc/mongod.conf --fork.使用命令1啓動的mongod服務在前臺運行,能夠經過Ctrl+C關閉服務。命令2啓動的mongod服務以守護線程的形式在後臺運行
使用命令2啓動服務端成功輸出如下信息:

about to fork child process, waiting until server is ready for connections.

forked process: 6775

child process started successfully, parent exiting

若是使用命令2啓動失敗輸出信息以下:

about to fork child process, waiting until server is ready for connections.

forked process: 6611

ERROR: child process failed, exited with error number 48

谷歌以後在stackoverflow上找到解決方案。這是由於已經有mongodb進程在運行,必須先找到該進程的pid,而後使用kill命令殺死該進程。

三、啓動mongo shell:
mongodb自帶Javascript Shell,能夠運行Javascript程序,並能夠和mongodb服務實例交互,啓動mongo shell命令是:

mongo

客戶端啓動後會自動鏈接到mongodb服務端的test數據庫:

MongoDB shell version: 3.2.7

connecting to: test

Welcome to the MongoDB shell.

For interactive help, type "help".

For more comprehensive documentation, see

http://docs.mongodb.org/

Questions? Try the support group

http://groups.google.com/group/mongodb-user

Server has startup warnings: 

2016-06-13T10:25:10.288+0800 I CONTROL [initandlisten] 

2016-06-13T10:25:10.288+0800 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. Number of files is 256, should be at least 1000
>

關閉mongo shell:
mongo shell有2種關閉方式:
1.運行mongo shell的終端輸入 control+c
2.從運行mongo shell的終端輸入> exit
至此,mongodb已經徹底安裝完畢!

  • 構建後端項目

一、新建一個文件夾,打開該文件夾,在終端輸入如下命令初始化項目:

npm init

二、安裝express生成器,經過應用生成器工具 express-generator 能夠快速建立一個應用的骨架。express-generator 包含了 express 命令行工具。經過以下命令便可安裝:

npm install express-generator -g

三、以下命令建立了一個名稱爲 myapp 的 Express 應用。此應用將在當前目錄下的 myapp 目錄中建立,而且設置爲使用 Pug 模板引擎:

express --view=pug myapp

四、而後安裝全部依賴包:

cd myapp
npm install

五、安裝nodemon。nodemon將監視啓動目錄中的文件,若是有任何文件更改,nodemon將自動從新啓動node應用程序。
全局安裝:

npm install -g nodemon

本地安裝:

npm install --save-dev nodemon

六、啓動項目

nodemon

出現以下:

~/code/lp-node-test/myapp » nodemon            
[nodemon] 1.19.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node ./bin/www`

在瀏覽器輸入:http://localhost:3000,express項目初步創建成功。

七、安裝插件babel-register、babel-preset-env,以便在項目中使用es6語法

npm install --save babel-register babel-preset-env

在根目錄下新建.babelrc文件,並輸入一下內容:

.babelrc

{
  "presets": ["env"]
}

八、安裝mongoose、mongoose-auto-increment、consola,鏈接mongodb數據庫

npm install --save mongoose mongoose-auto-increment consola

九、安裝session,用於用戶登陸認證

npm install --save express-session

十、在根目錄下建立config.js全局配置文件,並輸入以下:

config.js

const { argv } = require('yargs');

exports.MONGODB = {
    uri: `mongodb://127.0.0.1:${argv.dbport || '27017'}/node`,
    username: argv.db_username || 'DB_username',
    password: argv.db_password || 'DB_password',
};

十一、在根目錄下建立core文件夾,新建mongodb.js文件,並輸入以下:

core/mongodb.js

const consola = require('consola')
const CONFIG = require('../app.config.js')
const mongoose = require('mongoose')
const autoIncrement = require('mongoose-auto-increment')

// remove DeprecationWarning
mongoose.set('useFindAndModify', false)


// mongoose Promise
mongoose.Promise = global.Promise

// mongoose
exports.mongoose = mongoose

// connect
exports.connect = () => {
    // console.log('CONFIG.MONGODB.uri :', CONFIG.MONGODB.uri)

    // 鏈接數據庫
    mongoose.connect(CONFIG.MONGODB.uri, {
        useCreateIndex: true,
        useNewUrlParser: true,
        promiseLibrary: global.Promise
    })

    // 鏈接錯誤
    mongoose.connection.on('error', error => {
        consola.warn('數據庫鏈接失敗!', error)
    })

    // 鏈接成功
    mongoose.connection.once('open', () => {
        consola.ready('數據庫鏈接成功!')
    })

    // 自增 ID 初始化
    autoIncrement.initialize(mongoose.connection)
    
    // 返回實例
    return mongoose
}

十二、在根目錄下建立util文件夾,新建util.js文件,用於放置公共方法,並輸入以下:

util/util.js

import crypto from 'crypto';

module.exports = {
    md5: function(pwd) {
        let md5 = crypto.createHash('md5');
        return md5.update(pwd).digest('hex');
    },
    // 響應客戶端
    responseClient(res, httpCode = 500, status = 3, message = '服務端異常', data = {}) {
        let responseData = {};
        responseData.status = status;
        responseData.message = message;
        responseData.data = data;
        res.status(httpCode).json(responseData);
    },
    // 時間 格式化成 2018-12-12 12:12:00
    timestampToTime(timestamp) {
        const date = new Date(timestamp);
        const Y = date.getFullYear() + '-';
        const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
        const D = date.getDate() < 10 ? '0' + date.getDate() + ' ' : date.getDate() + ' ';
        const h = date.getHours() < 10 ? '0' + date.getHours() + ':' : date.getHours() + ':';
        const m = date.getMinutes() < 10 ? '0' + date.getMinutes() + ':' : date.getMinutes() + ':';
        const s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
        return Y + M + D + h + m + s;
    },
};

1三、在根目錄下建立models文件夾,新建建user.js,用於構建數據庫的數據模型,並輸入以下:

models/user.js

const crypto = require('crypto');
const { argv } = require('yargs');
const { mongoose } = require('../core/mongodb.js');
const autoIncrement = require('mongoose-auto-increment');

const adminSchema = new mongoose.Schema({
  // 名字
  name: { type: String, required: true, default: '' },

  //用戶類型 0:管理者,1:其餘用戶 
  type: { type: Number, required: true, default: 1 },

  // 手機
  phone: { type: Number, required: true, default: '' },

  // 郵箱
  email: { type: String,  required: true, default: '' },

  // 密碼
  password: {
    type: String,
    required: true,
    default: crypto
      .createHash('md5')
      .update(argv.auth_default_password || 'root')
      .digest('hex'),
  },

  // 建立日期
  create_time: { type: Date, default: Date.now },

  // 最後修改日期
  update_time: { type: Date, default: Date.now },
});
module.exports = mongoose.model('User', adminSchema);

1四、把app.js修改爲以下:

app.js

// modules
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const session = require('express-session');

// import 等語法要用到 babel 支持
require('babel-register');

const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(cookieParser('blog_node_cookie'));
app.use(
    session({
        secret: 'blog_node_cookie',
        name: 'session_id', //# 在瀏覽器中生成cookie的名稱key,默認是connect.sid
        resave: true,
        saveUninitialized: true,
        cookie: { maxAge: 60 * 1000 * 30, httpOnly: true }, //過時時間
    }),
);

const mongodb = require('./core/mongodb');

// data server
mongodb.connect();

//將路由文件引入
const route = require('./routes/index');

//初始化全部路由
route(app);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

1五、把routes/index.js修改以下:

routes/index.js

/*
*全部的路由接口
*/
const users = require('./users');

module.exports = app => {
    app.post('/login', users.login);
    app.post('/logout', users.logout);
    app.post('/register', users.register);
    app.post('/userInfo', users.userInfo);
    app.get('/currentUser', users.currentUser);
};

1六、把routes/users.js修改以下:

routes/users.js

const User = require('../models/user');
import { responseClient, md5 } from '../util/util.js';

exports.login = (req, res) => {
  const { phone, password } = req.body;
  const reg =/^1[34578]\d{9}$/
  if (!phone) {
    responseClient(res, 200, 400, '用戶郵箱不可爲空');
    return;
  }else if(!reg.test(phone)){
    responseClient(res, 200, 400, '請輸入格式正確的手機號碼');
    return;
  }
  if (!password) {
    responseClient(res, 200, 400, '密碼不可爲空');
    return;
  }
  User.findOne({
    phone,
    password: md5(password),
  })
    .then(userInfo => {
      console.log(userInfo._id)
      if (userInfo) {
        //登陸成功後設置session
        req.session.userInfo = userInfo;
        responseClient(res, 200, 200, '登陸成功', null);
      } else {
        responseClient(res, 200, 402, '用戶名或者密碼錯誤');
      }
    })
    .catch(err => {
      responseClient(res);
    });
};

//用戶驗證(獲取用戶信息)
exports.userInfo = (req, res) => {
  if (req.session.userInfo) {
    responseClient(res, 200, 200, '', req.session.userInfo);
  } else {
    responseClient(res, 200, 403, '請從新登陸', req.session.userInfo);
  }
};

exports.logout = (req, res) => {
  console.log(req.session)
  if (req.session.userInfo) {
    req.session.userInfo = null; // 刪除session
    responseClient(res, 200, 200, '登出成功!!');
  } else {
    responseClient(res, 200, 402, '您還沒登陸!!!');
  }
};

exports.register = (req, res) => {
  const { name, password, phone, type,email } = req.body;
  const regPhone =/^1[34578]\d{9}$/
  const regEmail = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/
  if (!phone) {
    responseClient(res, 200, 400, '用戶手機號碼不能爲空');
    return;
  }else if(!regPhone.test(phone)){
    responseClient(res, 200, 400, '請輸入格式正確的手機號碼');
    return;
  }
  if (!name) {
    responseClient(res, 200, 400, '用戶名不可爲空');
    return;
  }
  if (!email) {
    responseClient(res, 200, 400, '用戶郵箱不可爲空');
    return;
  }else if(!regEmail.test(email)){
    responseClient(res, 200, 400, '請輸入格式正確的郵箱');
    return;
  }
  if (!password) {
    responseClient(res, 200, 400, '用戶密碼不可爲空');
    return;
  }
  //驗證用戶是否已經在數據庫中
  User.findOne({ phone })
    .then(data => {
      if (data) {
        responseClient(res, 200, 402, '用戶手機號碼已存在!');
        return;
      }
      //保存到數據庫
      let user = new User({
        name,
        password: md5(password),
        phone,
        type,
        email
      });
      user.save().then(data => {
        responseClient(res, 200, 200, '註冊成功', data);
      });
    })
    .catch(err => {
      responseClient(res);
      return;
    });
};

exports.delUser = (req, res) => {
  let { id } = req.body;
  User.deleteMany({ _id: id })
    .then(result => {
      if (result.n === 1) {
        responseClient(res, 200, 0, '用戶刪除成功!');
      } else {
        responseClient(res, 200, 1, '用戶不存在');
      }
    })
    .catch(err => {
      responseClient(res);
    });
};

好了,如今用戶註冊、登陸、登出、用戶信息、刪除用戶接口都有了,使用postman請求接口試試
註冊:
圖片描述

登陸:
clipboard.png

其餘接口可自行補充,git地址:https://github.com/SuperMrBea...

相關文章
相關標籤/搜索