考试引擎

发布: (2026年1月1日 GMT+8 02:44)
6 min read
原文: Dev.to

I’m happy to help translate the article, but I don’t see the text you’d like translated—only the source link is provided. Could you please paste the content you want translated (excluding any code blocks or URLs you want to keep unchanged)? Once I have the text, I’ll translate it into Simplified Chinese while preserving the original formatting.

Source:

第5章:考试引擎

本章是整个 LMS 系统的 最关键核心。在此阶段,Academic Suite 不再仅仅管理静态数据,而是开始实时处理 时间、状态和用户行为

考试引擎负责确保:

  • 考试只能在指定时间访问
  • 每位学生获得公平的时间分配
  • 即使在刷新、重新连接或网络中断的情况下,考试状态仍保持一致

这部分的细微错误可能导致 评分不公,甚至 考试系统泄漏

5.1 设计理念:Quiz 与 ExamBatch

在线考试系统的常见错误是把 题目内容考试安排 混为一个实体。Academic Suite 明确将两者分离:

Quiz

题目及答案选项的集合。它是 静态 的,可复用。

ExamBatch

针对特定情境(班级、时间、令牌)的考试管理表示。它是 动态 的。

这种分离的好处

通过分离,同一套 Quiz 可以多次使用而无需数据重复:

  • Quiz “基础数学” → 班级 A 批次(周一 08:00)
  • 同一 Quiz → 班级 B 批次(周二 10:00)

这种做法使系统:

  • 更加灵活
  • 更易扩展
  • 对日程变更更安全

5.2 考试状态机

考试是一个 基于时间 的过程,其状态必须自动变化:

  • scheduled
  • active
  • finished

Academic Suite 并未使用 cron 任务 定期更新批次状态,而是采用 惰性状态更新(Lazy State Update)方式。

惰性状态更新

每次收到请求时,依据当前服务器时间评估考试状态。实现位于 handlers/batch.go

func GetBatches(c *fiber.Ctx) {
    now := time.Now()

    if now.After(batch.StartTime) && now.Before(batch.EndTime) {
        batch.Status = "active"
    } else if now.After(batch.EndTime) {
        batch.Status = "finished"
    }
}

这种方式的好处

  • 不需要后台工作者
  • 没有状态不同步的风险
  • 逻辑简单,易于测试

考试状态始终与实际服务器时间保持一致。

5.3 安全计时器:服务器端时间权威

在线考试系统的致命错误是 信任客户端时间。学生浏览器或操作系统的时钟可以被篡改,因此基于 JavaScript 的计时器不能作为真相来源。

解决方案:服务器端时间权威

Academic Suite 将 服务器 设为唯一的时间真相来源。前端定期调用接口:

GET /api/attempts/:id/time

后端根据以下信息计算剩余时间:

  • 考试开始时间
  • 总暂停时间
  • 批次时长
elapsed := time.Now().Sub(attempt.StartedAt)
effectiveElapsed := elapsed - attempt.TotalPausedTime
remaining := batch.Duration - effectiveElapsed

如果 remaining <= 0,后端会果断:

  • 拒绝新的答案提交
  • 自动结束本次尝试

采用此方式后,客户端的时间篡改变得无关紧要。

5.4 考试暂停与恢复功能

在真实场景中,考试可能因停电、网络中断或紧急情况被中断。Academic Suite 提供 冻结 / 恢复批次 功能。

暂停机制

当批次被 暂停 时,后端记录 PausedAt。在暂停状态下,学生的计时不会下降。

恢复机制

批次恢复时,计算 PausedAt 与当前时间之间的差值并累加到 TotalPausedTime。这确保:

  • 所有学生都得到公平的时间对待
  • 没有尝试因系统控制之外的因素而受到不利影响

5.5 考试令牌

作为额外的安全层,每个 ExamBatch 都可以使用 考试令牌 进行保护。即使学生已登录并且考试时间…(未完)

e 处于激活状态时,学生 无法在未输入有效令牌的情况下开始尝试

考试令牌的好处

  • 防止学生提前进入
  • 降低考试被未授权人员访问的风险
  • 为监考员提供完全控制权

这些令牌是可选的,但强烈建议在正式考试中使用。

章节概述

在本章中,我们构建了 exam engine,Academic Suite 的核心。我们涵盖了:

  • 考试内容与上下文的分离
  • 基于时间的状态机,采用惰性更新
  • 安全的服务器端计时器
  • 暂停与恢复机制
  • 通过考试令牌提供的额外安全

然而,考试系统若不保护 数据完整性和参与者行为,仍然不够安全。在 第 6 章,我们将讨论 数据完整性与防作弊 策略,包括处理重新连接、多标签页以及其他作弊尝试。

Back to Blog

相关文章

阅读更多 »