Skip to content

后端中间件

后端使用 Nitro 的中间件系统在全球范围内执行安全、日志记录和运营逻辑。中间件文件位于 apps/backend-api/src/middleware/,并按数字/字母顺序执行。

中间件执行管线

文件名中的数字决定了执行顺序。这种层级结构对安全至关重要:

  1. 0.5.correlation.ts: 链路追踪设置。
  2. 0.maintenance.ts: 全局锁定开关。
  3. 1.logger.ts: 请求日志记录。
  4. 2.auth.ts: 身份认证与 RBAC。
  5. 2.5.csrf.ts: CSRF 保护。
  6. 3.ratelimit.ts: 速率限制。

1. 链路追踪 (0.5.correlation.ts)

目的: 为每个请求分配一个唯一的 ID,以便在日志和服务之间进行追踪。

  • 逻辑:
    1. 检查请求头 X-Correlation-IDX-Request-ID 中是否存在 ID(对微服务很有用)。
    2. 如果缺失,则生成一个新的 UUID
    3. 将该 ID 附加到 event.context
    4. 响应头中设置 X-Correlation-ID

2. 维护模式 (0.maintenance.ts)

目的: 允许管理员锁定系统进行升级,同时保持自己可以访问。

  • 配置键: maintenance_mode(在 SystemConfig 表中)。
  • 逻辑:
    1. 排除: 跳过 /api/health/api/status,以便监控工具不会发出虚假报警。
    2. 检查全局 maintenance_mode 设置。
    3. 如果已启用:
      • 验证用户认证。
      • 绕过: 如果用户拥有 super 角色,则允许请求。
      • 拦截: 对所有其他用户返回 503 Service Unavailable

3. 操作日志 (1.logger.ts)

目的: 记录所有 API 交互的详细审计轨迹。

  • 数据源: 从由其他中间件填充的 event.context 中读取(用户、关联 ID、旧值/新值)。
  • 存储: 写入 OperationLog 数据库表。
  • 逻辑:
    1. 排除: 跳过 /health, /test/uploads/ 以减少噪音。
    2. 挂载到响应的 finish 事件,以捕获最终的 HTTP 状态码和执行时长。
    3. 记录:用户、IP、路径、方法、参数和时长。
    4. 上下文: 如果由路由处理器设置,可以捕获 operationDescription (操作描述)、oldValue (旧值) 和 newValue (新值)。

4. 身份认证与 RBAC (2.auth.ts)

目的: 核心安全守门人。处理身份识别(你是谁?)和权限控制(你能做这个吗?)。

  • 逻辑:
    1. 公共路径: 跳过对登录、刷新、MFA 和健康检查接口的验证。
    2. 身份认证 (AuthN):
      • 验证 JWT 访问令牌。
      • 会话检查: 根据 UserSession 表进行验证,确保会话未被撤销或过期。
      • 更新会话的 lastActiveAt 时间戳。
    3. 权限授权 (AuthZ):
      • 超级管理员: 绕过所有权限检查。
      • 路由匹配: 将请求路径(如 /api/users)与数据库中的 ApiPermission 记录匹配。
      • 权限校验: 验证用户的角色是否链接到该 ApiPermission
      • 缓存: 使用 Valkey (Redis) 缓存角色权限查询结果以提高性能 (perms:role:...)。
    4. 结果:
      • 如果是无效令牌/会话,返回 401 Unauthorized
      • 如果角色没有权限,返回 403 Forbidden

5. CSRF 保护 (2.5.csrf.ts)

目的: 使用双重提交 Cookie 模式防止跨站请求伪造 (CSRF) 攻击。

  • 模式: 同时要求一个 Cookie (XSRF-TOKEN) 和一个匹配的请求头 (X-XSRF-TOKEN)。
  • 逻辑:
    1. 排除:
      • 安全方法: GET, HEAD, OPTIONS
      • 公共路径: 登录、刷新、MFA。
      • 上传: /uploads/ (通过其他方式处理)。
    2. 从 Cookie 和请求头中读取令牌。
    3. 验证:
      • 两者必须同时存在。
      • 两者必须完全匹配。
    4. 结果: 如果不匹配,返回 403 Forbidden

6. 速率限制 (3.ratelimit.ts)

目的: 保护 API 免受滥用、暴力破解和 DoS 攻击。

  • 存储: 使用 RateLimit 表 (PostgreSQL)。
  • 规则:
    • 认证接口: 15 分钟内 100 次请求(严格)。
    • 用户创建: 1 小时内 50 次请求(防垃圾)。
    • 密码重置: 1 小时内 5 次请求(高安全性)。
    • 文件上传: 1 小时内 100 次请求。
    • 通用 API: 1 分钟内 60 次请求。
  • 逻辑:
    1. 根据请求路径识别匹配的规则。
    2. 原子计数: 执行数据库 Upsert(插入或更新)以增加该 IP 地址的计数器。
    3. 执行:
      • 如果计数 > 限制,返回 429 Too Many Requests
      • 返回 Retry-After (稍后重试) 消息。