教程 express tutorial

登录与用户中心

在本章节中,我们将通过构建一个简单的登录与用户中心系统,介绍如何在 Express 中实现用户身份认证、登录状态管理以及用户信息的查看与修改。我们将使用 Passport.js 来处理用户认证,JWT 用于会话管理,并且实现基本的用户信息存储与管理。

1. 安装依赖

首先,您需要安装用于处理身份认证和用户登录的必要依赖:

bash
npm install passport passport-local jsonwebtoken bcryptjs

`

  • passport:用于处理身份验证的中间件。
  • passport-local:实现本地用户名和密码认证策略。
  • jsonwebtoken (JWT):用于创建和验证 JSON Web Tokens,用于会话管理。
  • bcryptjs:用于加密和验证用户密码。

2. 设置 Passport.js 认证

2.1 用户模型设计

我们将使用 Mongoose 来创建一个用户模型,包含用户名、密码、邮箱和注册时间等基本信息。

js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');

// 创建用户模型
const userSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  createdAt: { type: Date, default: Date.now },
});

// 加密密码
userSchema.pre('save', async function (next) {
  if (!this.isModified('password')) return next();

  this.password = await bcrypt.hash(this.password, 10);
  next();
});

// 比较密码
userSchema.methods.comparePassword = function (candidatePassword) {
  return bcrypt.compare(candidatePassword, this.password);
};

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

module.exports = User;

2.2 配置 Passport.js

我们将使用 Passport 的 local strategy 来处理用户名和密码的身份验证。

js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/User');

// 配置 Passport 本地策略
passport.use(new LocalStrategy(
  async (username, password, done) => {
    try {
      const user = await User.findOne({ username });
      if (!user) return done(null, false, { message: 'Incorrect username' });

      const isMatch = await user.comparePassword(password);
      if (!isMatch) return done(null, false, { message: 'Incorrect password' });

      return done(null, user);
    } catch (err) {
      return done(err);
    }
  }
));

// 序列化用户
passport.serializeUser((user, done) => {
  done(null, user.id);
});

// 反序列化用户
passport.deserializeUser(async (id, done) => {
  try {
    const user = await User.findById(id);
    done(null, user);
  } catch (err) {
    done(err);
  }
});

3. 用户注册与登录路由

3.1 用户注册

用户需要提供用户名、邮箱和密码来注册。我们将使用 POST 请求处理注册,并在数据库中保存用户信息。

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

const router = express.Router();

// 注册路由
router.post('/register', async (req, res) => {
  const { username, email, password } = req.body;

  try {
    const existingUser = await User.findOne({ username });
    if (existingUser) return res.status(400).json({ message: 'Username already taken' });

    const newUser = new User({ username, email, password });
    await newUser.save();
    res.status(201).json({ message: 'User registered successfully' });
  } catch (err) {
    res.status(500).json({ message: 'Error registering user', error: err });
  }
});

3.2 用户登录

用户可以使用用户名和密码进行登录,成功后返回一个 JWT,用于后续的请求认证。

js
const jwt = require('jsonwebtoken');

// 登录路由
router.post('/login', passport.authenticate('local', { session: false }), (req, res) => {
  const user = req.user;

  // 生成 JWT
  const token = jwt.sign({ id: user.id, username: user.username }, 'secretKey', { expiresIn: '1h' });

  res.status(200).json({
    message: 'Login successful',
    token: token,
    user: {
      id: user.id,
      username: user.username,
      email: user.email,
    }
  });
});

3.3 用户中心

登录后,用户可以通过访问用户中心查看和修改个人信息。我们通过验证 JWT 来保护该路由。

js
const jwtMiddleware = require('../middleware/jwtMiddleware');  // 自定义的 JWT 校验中间件

// 用户中心路由,保护路由,仅允许已认证用户访问
router.get('/user-center', jwtMiddleware, async (req, res) => {
  try {
    const user = await User.findById(req.user.id);
    if (!user) return res.status(404).json({ message: 'User not found' });

    res.status(200).json({
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        createdAt: user.createdAt,
      }
    });
  } catch (err) {
    res.status(500).json({ message: 'Error retrieving user data', error: err });
  }
});

4. JWT 验证中间件

我们需要创建一个中间件来验证 JWT,以便保护需要用户登录的路由。

js
const jwt = require('jsonwebtoken');

const jwtMiddleware = (req, res, next) => {
  const token = req.headers['authorization'];

  if (!token) return res.status(403).json({ message: 'No token provided' });

  jwt.verify(token, 'secretKey', (err, decoded) => {
    if (err) return res.status(401).json({ message: 'Invalid or expired token' });

    req.user = decoded;  // 将解码后的用户信息添加到请求中
    next();
  });
};

module.exports = jwtMiddleware;

5. 用户信息更新

用户可以更新自己的个人信息,例如修改邮箱或密码。我们将提供一个 PUT 路由来处理更新请求。

js
router.put('/user-center', jwtMiddleware, async (req, res) => {
  const { email, password } = req.body;
  const { id } = req.user;

  try {
    const user = await User.findById(id);
    if (!user) return res.status(404).json({ message: 'User not found' });

    if (email) user.email = email;
    if (password) user.password = await bcrypt.hash(password, 10);  // 加密新密码

    await user.save();
    res.status(200).json({ message: 'User information updated' });
  } catch (err) {
    res.status(500).json({ message: 'Error updating user data', error: err });
  }
});

6. 总结

通过本章节的实现,您已经掌握了如何在 Express 中构建一个基本的登录和用户中心系统。您学会了如何:

  1. 使用 Passport.js 进行身份验证,处理用户的登录请求。
  2. 使用 JWT 来管理用户的会话,并实现对用户中心等敏感路由的保护。
  3. 创建用户注册和登录功能,处理用户信息的更新。

您可以根据需要扩展更多的功能,如密码重置、用户角色管理等,来进一步完善该系统。