返回

Node.js 轻量级后台系统开发,新手入门必学!

后端

Node.js 轻量级后台系统开发,新手入门必学!

Node.js 是一个事件驱动的、非阻塞式 I/O 模型的 JavaScript 运行时,非常适合构建高性能、可扩展的网络应用程序。本指南将带领您一步一步构建一个 Node.js 后台系统,涵盖了注册、登录、获取用户信息等常见功能。适合新手入门,快速掌握 Node.js 后端开发技巧。

前言

Node.js 凭借其高性能、可扩展性、易用性等优点,成为越来越多开发者构建后端系统的首选语言。本指南将从零开始,带领您一步一步构建一个 Node.js 后台系统。我们将使用 Express 作为 Web 框架,MongoDB 作为数据库,并使用 Passport.js 来处理用户身份认证。

项目结构

├── app.js              # 主应用程序文件
├── controllers         # 控制器文件夹
│   ├── auth.js          # 用户身份认证控制器
│   ├── user.js           # 用户信息控制器
├── models              # 模型文件夹
│   ├── user.js           # 用户模型
├── routes              # 路由文件夹
│   ├── auth.js          # 用户身份认证路由
│   ├── user.js           # 用户信息路由
├── views               # 视图文件夹
│   ├── index.html        # 首页模板
│   ├── auth              # 用户身份认证模板
│   │   ├── login.html     # 登录模板
│   │   ├── register.html  # 注册模板
│   ├── user              # 用户信息模板
│   │   ├── profile.html   # 个人资料模板
│   │   ├── edit.html      # 编辑个人资料模板
├── package.json        # 项目依赖文件
├── node_modules       # 项目依赖包文件夹

安装依赖

npm install express mongodb passport passport-local mongoose ejs

配置 Express

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

// 设置模板引擎
app.set('view engine', 'ejs');

// 使用中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 定义路由
app.use('/auth', require('./routes/auth'));
app.use('/user', require('./routes/user'));

// 启动服务器
app.listen(3000, () => {
  console.log('Server is listening on port 3000');
});

配置 MongoDB

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/node-js-backend', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

const db = mongoose.connection;

db.on('error', console.error.bind(console, 'MongoDB connection error:'));

db.once('open', () => {
  console.log('MongoDB connected');
});

配置 Passport.js

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password',
}, (email, password, done) => {
  User.findOne({ email }, (err, user) => {
    if (err) { return done(err); }
    if (!user) { return done(null, false); }
    if (!user.verifyPassword(password)) { return done(null, false); }
    return done(null, user);
  });
}));

passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  User.findById(id, (err, user) => {
    done(err, user);
  });
});

app.use(passport.initialize());
app.use(passport.session());

构建用户模型

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  name: { type: String, required: true },
});

userSchema.methods.verifyPassword = function(password) {
  return bcrypt.compareSync(password, this.password);
};

const User = mongoose.model('User', userSchema);

module.exports = User;

构建用户控制器

const User = require('../models/user');
const passport = require('passport');

exports.login = (req, res) => {
  res.render('auth/login');
};

exports.register = (req, res) => {
  res.render('auth/register');
};

exports.postLogin = (req, res, next) => {
  passport.authenticate('local', (err, user, info) => {
    if (err) { return next(err); }
    if (!user) { return res.render('auth/login', { error: info.message }); }
    req.logIn(user, (err) => {
      if (err) { return next(err); }
      res.redirect('/user/profile');
    });
  })(req, res, next);
};

exports.postRegister = (req, res, next) => {
  const newUser = new User({
    email: req.body.email,
    password: req.body.password,
    name: req.body.name,
  });

  User.register(newUser, req.body.password, (err, user) => {
    if (err) { return res.render('auth/register', { error: err.message }); }
    req.logIn(user, (err) => {
      if (err) { return next(err); }
      res.redirect('/user/profile');
    });
  });
};

exports.getProfile = (req, res) => {
  res.render('user/profile', { user: req.user });
};

exports.getEditProfile = (req, res) => {
  res.render('user/edit', { user: req.user });
};

exports.postEditProfile = (req, res) => {
  const updatedUser = {
    email: req.body.email,
    name: req.body.name,
  };

  User.findByIdAndUpdate(req.user._id, updatedUser, { new: true }, (err, user) => {
    if (err) { return res.render('user/edit', { error: err.message }); }
    res.redirect('/user/profile');
  });
};

构建用户路由

const express = require('express');
const router = express.Router();

const authController = require('../controllers/auth');
const userController = require('../controllers/user');

router.get('/login', authController.login);
router.get('/register', authController.register);
router.post('/login', authController.postLogin);
router.post('/register', authController.postRegister);

router.get('/profile', userController.getProfile);
router.get('/edit', userController.getEditProfile);
router.post('/edit', userController.postEditProfile);

module.exports = router;

构建模板

index.html

<!DOCTYPE html>
<html>
<head>
  
</head>
<body>
  <h1>Node.js Backend</h1>
  <a href="/auth/login">Login</a>
  <a href="/auth/register">Register</a>
</body>
</html>

auth/login.html

<!DOCTYPE html>
<html>
<head>
  
</head>
<body>
  <h1>Login</h1>
  <form action="/auth/login" method="POST">
    <label for="email">Email:</label>
    <input type="email" name="email" id="email" required>
    <br>
    <label for="password">Password:</label>
    <input type="password" name="password" id="password" required>
    <br>
    <button type="submit">Login</button>
  </form>
</body>
</html>

auth/register.html

<!DOCTYPE html>
<html>
<head>