0

我正在建立一个调查页面,用户可以在有限的时间内回答他们所有的问题。给定的时间以@test.time_allowed 的形式存储在模型中,它是一个表示秒数的整数。

我需要一种简单且用户不可篡改的方法来让计时器显示在视图上,并在它降至 0 时执行控制器操作。我该如何做到这一点?

我是一个相对初学者,所以任何具体的答案都会非常有帮助。谢谢你。

- -更新 - -

@Bryan:
我认为如果计时是在服务器端完成的,那么有一种防篡改方式吗?例如,如您所建议的,客户端可能有一个 javascript 计时器,但是在提交时不能根据窗口的初始加载时间检查提交时间吗?

4

3 回答 3

2

由于从客户端返回的数据永远无法完全信任,因此服务器必须以某种方式知道最初生成的表单的时间戳是什么。这可以通过在会话或数据库中保存变量来完成,但这是有问题的。相反,服务器可以在表单中放置一个时间戳,无论是加密的还是签名的,以确保客户端没有更改它。然后,服务器可以根据需要拒绝提交。在客户端,单独的逻辑可以处理 UI 部分,给用户关于时间限制的反馈,但最终这只是松散地耦合到服务器处理。

细节:

服务器应该生成两个表单域:一个带有系统时间戳time = Time.now.to_i,用于跟踪表单的生成时间,另一个带有签名Digest::MD5.hexdigest(time.to_s.concat('Some-secret-string-1234'))(注意这里时间戳表单域和签名表单域使用相同的时间值)。这将验证表单是否使用客户端未更改的服务器生成的时间戳提交。

您也可以发送另一个带有时间限制的表单域。

在客户端,读取时间戳,使用 setTimeout 和时间限制来生成倒计时或任何你想在前端做的事情。

提交表单时,通过使用与以前相同的方法重新生成 MD5 签名来验证随表单提交的时间戳。确保它与表单提交的签名相匹配。然后,将时间戳添加到超时,并确保它晚于当前服务器时间。如果是这样,您有一个有效的提交,在您的时间限制内。

您可能需要在服务器超时比客户端多一点余地,可能是几秒钟,以解决网络延迟,否则用户可能会看到剩余一秒钟,单击提交,然后到收到服务器请求时,似乎计时器已过期。

请务必添加require 'digest/md5'以访问 MD5。

Using MD5 signatures like this is a great way to verify that a client has not altered key parameters in a form in a stateless manner, whatever you would like them to be. A good addition to your bag of tricks.

Good luck!

于 2010-07-21T17:45:34.620 回答
0

没有 100% 防篡改的方式来实现这一点,因为您需要使用 JavaScript 来执行此操作,该 JavaScript 可以被足够恶意的用户关闭或操纵。

但是,如果您不关心这些问题,您可以简单地在页面上设置超时以在秒数过去后提交表单。为此,您需要类似于以下内容。显然timeInMilliseconds需要从服务器端的模板生成到页面中。

window.setTimeout(function() {
                     document.forms['survey_form'].submit();
                  },
                  timeInMilliseconds);
于 2010-07-21T06:08:48.320 回答
0

Create model for ongoing surveys, and add after_create filter that will set deadline to Time.now + survey_duration. Keep logic that will deny late sending of answers in model.

于 2010-07-21T17:45:40.673 回答