首页 > 解决方案 > JavaScript 无法破解的倒数计时器

问题描述

我目前正在开发一个测验应用程序。当一个问题出现时,用户有 10 秒的时间来回答它,否则他们不会得到该问题的分数。一旦计时器到了,我想自动转到下一个问题。我目前面临有关如何使客户端“无法破解” 10 秒倒计时计时器的问题。

我最初的想法是setTimeout()在客户端使用类似的东西 10 秒,一旦计时器完成,要求服务器获取下一个问题。这样做的问题是客户端计时器可以被破解/修改为运行超过 10 秒,从而可能给一些用户超过 10 秒的时间来回答问题。

client <--- sends question --- server
  |
start timer for 10 seconds (as this is client-side, it could easily be extended)
  |
  .
10 seconds later 
  .
  V
client --- ask for next question / send answer ---> server

为了让它不被破解,我想把时间检查逻辑移到服务器端。这将涉及在每个连接的用户的服务器端保留两个变量 (AB),一个表示发送问题的时间,另一个表示给出答案的时间。客户端计时器仍将运行,除了服务器端使用时间戳执行一些验证以检查时间戳 A 和 B 之间的差异是否超过 10 秒:

client <--- sends question --- server (send question at timestamp `A`)
  |
start timer for 10 seconds (as this is client-side, it could easily be extended)
  |
  .
10 seconds later 
  .
  V
client --- ask for next question / send answer ---> server (receive request at timestamp `B`)
                                                      |
+-----------------------------------------------------+
v
server logic:
  duration = B - A
  if(duration > 10 seconds) {
    // allocated time exceeded
  }

但是,我看到了一些潜在的缺陷。问题从服务器到达客户端所需的时间与服务器发送问题之间的时间(时间A) 到客户端计时器启动的时间不会是临时性的,并且将取决于用户对服务器的 ping / 连接。当客户询问下一个问题时,存在类似的 ping 问题。此外,我担心如果应该运行 10 秒的客户端计时器滞后一点,那么它也会导致服务器端检查失败。因此,检查持续时间是否超过 10 秒是不够的,它需要一些额外的缓冲区。但是,我觉得将缓冲区任意硬编码为 1 或 2 秒可能仍会导致问题,并且感觉像是一种不太可靠的变通方法。

问题:我想知道我是否缺少一种不同的方法来保持客户端计时器不可破解和准确。我还想尝试避免setTimeout()在服务器端为每个连接的用户创建单独的计时器或类似的计时器,因为许多用户可以在一个给定的时间点连接,并且在服务器上排队的这么多计时器感觉资源不足。我还想尽量减少在客户端和服务器之间来回发送的消息数量。

标签: javascriptnode.jsservercountdown

解决方案


而不是在发送问题时启动服务器上的时钟。当问题显示给用户(在客户端)时,您可以在服务器上启动时钟。

  • 维护2个时钟一个在客户端另一个在服务器上。
  • 每个时间敏感请求的时间戳(Start quiz timerEnd quiz timer检查时间戳差异是否在可接受的容差范围内。

测验应用同步问题


推荐阅读