由于从客户端返回的数据永远无法完全信任,因此服务器必须以某种方式知道最初生成的表单的时间戳是什么。这可以通过在会话或数据库中保存变量来完成,但这是有问题的。相反,服务器可以在表单中放置一个时间戳,无论是加密的还是签名的,以确保客户端没有更改它。然后,服务器可以根据需要拒绝提交。在客户端,单独的逻辑可以处理 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!