返回

Egg.js从零开始打造实用后端

前端

使用 Egg.js 构建可扩展的后端应用程序:用户管理与路由鉴权指南

简介

在当今快节奏的数字时代,企业需要强大的后端应用程序来管理数据、处理请求并提供无缝的用户体验。Egg.js,一个基于 Koa2 的 Node.js 框架,凭借其轻量级、模块化和可扩展性,已成为构建健壮后端解决方案的首选。

本指南将深入探讨如何使用 Egg.js 构建一个全面的后端应用程序,包括用户管理和路由鉴权功能。我们将指导您完成从设置到实现每个功能的各个步骤。

准备工作

在开始之前,您需要:

  • 安装 Node.js 10.0 或更高版本
  • 安装 npm 6.0 或更高版本
  • 安装 Egg.js 2.0 或更高版本

创建 Egg.js 应用程序

  1. 使用以下命令创建一个新的 Egg.js 应用程序:
npm init egg my-app
  1. 这将创建一个名为“my-app”的新目录,其中包含一个基本的 Egg.js 应用程序。

安装依赖项

为了构建我们的用户管理和路由鉴权功能,我们需要安装一些依赖项:

  • egg-sequelize:用于连接数据库
  • egg-jwt:用于实现 JWT 身份验证
  • egg-cors:用于允许跨域请求

使用以下命令安装这些依赖项:

npm install egg-sequelize egg-jwt egg-cors --save

连接数据库

使用 Sequelize 连接到数据库,它是一个流行的 ORM,用于 Node.js。

  1. 在 config/config.default.js 文件中配置数据库连接信息:
module.exports = {
  sequelize: {
    dialect: 'mysql',
    host: 'localhost',
    port: 3306,
    database: 'my_database',
    username: 'root',
    password: 'password'
  }
};
  1. 在 app/model 目录中创建 User 模型文件:
module.exports = app => {
  const { STRING, INTEGER, DATE } = app.Sequelize;

  const User = app.model.define('user', {
    id: {
      type: INTEGER,
      primaryKey: true,
      autoIncrement: true
    },
    username: {
      type: STRING(30),
      allowNull: false,
      unique: true
    },
    password: {
      type: STRING(60),
      allowNull: false
    },
    created_at: {
      type: DATE,
      allowNull: false,
      defaultValue: app.Sequelize.literal('CURRENT_TIMESTAMP')
    },
    updated_at: {
      type: DATE,
      allowNull: false,
      defaultValue: app.Sequelize.literal('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')
    }
  });

  return User;
};

实现用户管理

用户注册

  1. 在 app/controller/user.js 文件中创建 UserController:
module.exports = app => {
  class UserController extends app.Controller {
    async register() {
      const { ctx } = this;
      const { username, password } = ctx.request.body;

      // 检查用户名是否已经存在
      const user = await ctx.model.User.findOne({ where: { username } });
      if (user) {
        ctx.body = {
          code: 400,
          message: '用户名已存在'
        };
        return;
      }

      // 创建新用户
      const newUser = await ctx.model.User.create({
        username,
        password
      });

      // 返回注册成功的消息
      ctx.body = {
        code: 200,
        message: '注册成功'
      };
    }
  }

  return UserController;
};
  1. 在 config/router.js 文件中配置路由:
module.exports = app => {
  const { controller } = app;

  app.post('/api/user/register', controller.user.register);
};

用户登录

  1. 在 app/controller/user.js 文件中更新 UserController:
module.exports = app => {
  class UserController extends app.Controller {
    async login() {
      const { ctx } = this;
      const { username, password } = ctx.request.body;

      // 检查用户名是否存在
      const user = await ctx.model.User.findOne({ where: { username } });
      if (!user) {
        ctx.body = {
          code: 400,
          message: '用户名不存在'
        };
        return;
      }

      // 检查密码是否正确
      const isPasswordCorrect = await user.comparePassword(password);
      if (!isPasswordCorrect) {
        ctx.body = {
          code: 400,
          message: '密码错误'
        };
        return;
      }

      // 生成 JWT 令牌
      const token = app.jwt.sign({ id: user.id, username: user.username });

      // 返回登录成功的消息和 JWT 令牌
      ctx.body = {
        code: 200,
        message: '登录成功',
        token
      };
    }
  }

  return UserController;
};
  1. 在 config/router.js 文件中更新路由:
module.exports = app => {
  const { controller } = app;

  app.post('/api/user/login', controller.user.login);
};

实现路由鉴权

为了保护我们的 API 路由,我们需要实现路由鉴权。

  1. 在 app/middleware/auth.js 文件中创建 AuthMiddleware:
module.exports = app => {
  class AuthMiddleware extends app.Middleware {
    async before(ctx) {
      const { authorization } = ctx.request.headers;
      if (!authorization) {
        ctx.body = {
          code: 401,
          message: '未授权'
        };
        return;
      }

      const token = authorization.split(' ')[1];
      const decodedToken = await app.jwt.verify(token);
      if (!decodedToken) {
        ctx.body = {
          code: 401,
          message: '令牌无效'
        };
        return;
      }

      ctx.state.user = decodedToken;
    }
  }

  return AuthMiddleware;
};
  1. 在 config/router.js 文件中配置路由鉴权:
module.exports = app => {
  const { controller } = app;

  app.use('/api/user', app.middleware.auth());
  app.post('/api/user/register', controller.user.register);
  app.post('/api/user/login', controller.user.login);
};

常见问题解答

1. 如何配置不同的数据库方言?

要配置不同的数据库方言,请编辑 config/config.default.js 文件并更新 dialect 字段。例如,对于 PostgreSQL,请将 dialect 设置为 'postgres'。

2. 如何使用 Sequelize 执行其他数据库操作?

Sequelize 提供了广泛的方法和属性来执行 CRUD 和其他数据库操作。有关详细信息,请参阅 Sequelize 文档。

3. JWT 的有效期如何?

JWT 的有效期可以通过配置 egg-jwt 的 options 对象中的 expires 字段来控制。

4. 如何禁用路由鉴权?

要禁用路由鉴权,请注释掉 config/router.js 文件中的 app.use('/api/user', app.middleware.auth()); 行。

5. 如何处理未授权的请求?

当未经授权的请求尝试访问受保护的路由时,AuthMiddleware 将自动向客户端发送 401 未授权响应。

结论

使用 Egg.js 构建一个完整的后端应用程序包括用户管理和路由鉴权,可以为您的项目提供一个强大且可扩展的基础。通过遵循本指南中概述的步骤,您可以自信地创建健壮的后端解决方案,为您的用户提供卓越的体验。