我目前正在开发一个测验应用程序。当出现问题时,用户有 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
为了保持其不可破解,我想到将时间检查逻辑移至服务器端。这将涉及在每个连接用户的服务器端保留两个变量(
A
和B
),一个代表发送问题的时间,另一个代表给出答案的时间。客户端计时器仍然会运行,除非服务器端使用时间戳来执行一些验证以检查时间戳 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()
或类似的计时器,因为许多用户可以在一个给定的时间点连接,并且有这么多计时器在服务器上排队感觉没有资源。我还想尝试将客户端和服务器之间来回发送的消息数量保持在最低限度。
饼干怎么样?
设置带有唯一令牌的 cookie。将其到期时间设置为 now()+15 秒。在服务器端保存令牌和时间。让客户端计时器保持运行,并在 10 秒后自动提交。
当答案到来时,如果没有cookie...这肯定意味着答案是在延迟后发送的(并且计时器被黑客入侵)。
因此,now() + 10 秒的 cookie 过期时间 + 大约 5 秒的宽限期应该足以补偿 HTTP 延迟。
如果他们破解了计时器,则 cookie 应该已过期(并被删除)。如果他们还破解了 cookie 过期时间(!),无论如何,令牌将用于检索发送的问题的日期时间,您将其与收到的答案的日期时间进行比较。
2490 和 56 因为它是 caullel