在页面加载时加载时间戳,并将其与表单提交时的时间戳进行比较

Loading timestamp upon page load and comparing it to timestamp upon form submit

本文关键字:时间戳 加载 表单提交 比较      更新时间:2023-09-26

我已经在我的应用程序中开发了一个反垃圾邮件时间陷阱(是的,我知道它不会100%有效,但这是一个权宜之计),它是这样做的:

1)加载页面时,使用JavaScript用时间戳填充隐藏输入:

var timestamp = new Date().getTime() / 1000;

2)当表单被post时,使用Python视图根据当前时间检查这个时间戳——如果从页面加载到现在不到5秒,反弹一个异常:

import datetime
feedback_timestamp = request.POST['feedback_timestamp'].strip()
current_timestamp = datetime.datetime.now().timestamp()
if current_timestamp - float(feedback_timestamp) < 5:
    raise Exception("Submitted too quickly after loading!")

这在我的本地开发服务器上工作得很好(即它强制你等待5秒,否则它会抛出异常)。然而,我注意到,一旦我在生产服务器上加载它,时间戳之间的间隔大约是30秒,即使我在加载后立即提交了表单。似乎JavaScript函数从本地用户获取时间,而Python代码从服务器获取时间,因此,如果它们不同步,它将无法正确触发。

我的问题是:我如何从服务器而不是本地机器获取初始时间戳?是否有一个JavaScript函数可以做到这一点?或者我是否需要使用Python后端来填充隐藏的输入?

如果是后者,事情就有点复杂了,因为这一切都是在我的base.html中完成的,它从来没有被我的任何视图直接加载(也就是说,它被用来扩展我使用的许多其他视图)。在不使用与页面关联的视图的情况下,我如何从Python后端提取值?

如果你不想在视图中执行逻辑,你可以使用上下文处理器将变量发送给模板:

def add_timestamp_context(request):
    return {'current_time': datetime.datetime.now()}

或者类似的东西。点击这里了解更多细节。您需要将新函数添加到settings.py中的TEMPLATE_CONTEXT_PROCESSORS变量中,如文档所述。

你还应该注意,所有发送到模板的变量将在你的base.html中可用。因此,您可以将变量从关联视图发送到模板,它将工作,即使前端逻辑在您的base.html文件中。

在我看来,最好的解决方案是在前端计算两个戳记,而不是在后端。

您可以使用上下文处理器向每个模板添加时间戳上下文变量。你的上下文处理器是一个简单的Python函数,它接受一个HttpRequest参数并返回一个字典,该字典被添加到你的上下文字典中。

你的函数可能是这样的:

def timestamp(request):
    ctx = {
        'timestamp': timezone.now()
    }
    return ctx

然后,在您的settings.py中添加您的功能到TEMPLATE_CONTEXT_PROCESSORS:

TEMPLATE_CONTEXT_PROCESSORS = (
    ...,
    'path.to.function.context_processors.timestamp',
)

就是这样!