px 断缘技术站 notes & experiments

服务端计时与防作弊:在线考试系统里那些看不见的坑

技术笔记 · 系统设计 · 约 600 字

在线考试系统最容易被想简单的地方就是倒计时。前端写个 setInterval 每秒减一,看着挺对,实际上到处是漏洞。

一、倒计时不能信浏览器

用户改一下系统时间、打开开发者工具改个变量,或者只是切到后台标签页让定时器被浏览器节流,前端那点剩余时间立刻失真。正确做法是把「开始时间」记在服务端,页面只负责展示,真正的剩余时间永远由服务端算:

remaining = deadline_ts - time()

页面可以在开始时取一次截止时间,本地平滑地跑动画,但每次交卷都必须以服务端时间为准。宁可让用户看到的时间偶尔跳一下,也不能让浏览器说了算。

二、交卷要拒收超时负载

只在前端拦「时间到了」是拦不住的——请求照样发得出去,服务端照样收到。所以判卷入口必须先做一道服务端校验:超过截止时间的提交直接拒绝,而不是「先记下来晚了几秒」。时间容差可以留几秒给网络抖动,但绝不能留成几分钟的大口子。

三、隐藏测试与可见测试分家

如果同一份试卷、同一套答案既给考生看又拿来判分,等于把答案提前发下去了。做法是:可见题目只用于展示,判分走另一份只有服务端能读到的数据;考生提交的只是选项,服务端拿自己的题库对答案。

四、随机组卷的随机数要在服务端生成

客户端抽题等于把整份题库发给考生。即使前端只显示几道,抓个包也能看到全部内容。题目从服务端抽、答案不下发,才谈得上防作弊。

五、同一个道理

这些坑的共同点很一致:前端的一切都只是「界面」,能被看见的就能被绕过。凡是跟分数、时间、公平相关的判断,都必须放到用户改不到的地方去算。写业务的时候多想一步「这个值用户能不能改」,能省掉后面大部分返工。

← 返回技术笔记列表 · 返回首页