【问题标题】:How to build a Django form which requires a delay to be re-submitted?如何构建需要延迟重新提交的 Django 表单?
【发布时间】:2011-02-16 13:36:14
【问题描述】:

为了避免垃圾邮件,我想添加一个等待时间来重新提交表单(即用户应该等待几秒钟来提交表单,除了第一次提交表单之外)。

为此,我在表单中添加了一个timestamp(以及一个包含时间戳的security_hash 字段以及确保时间戳不会被篡改的settings.SECRET_KEY)。这看起来像:

class MyForm(forms.Form):
    timestamp     = forms.IntegerField(widget=forms.HiddenInput)
    security_hash = forms.CharField(min_length=40, max_length=40, widget=forms.HiddenInput)
    # + some other fields..

    # + methods to build the hash and to clean the timestamp...
    # (it is based on django.contrib.comments.forms.CommentSecurityForm)

    def clean_timestamp(self):
        """Make sure the delay is over (5 seconds)."""
        ts = self.cleaned_data["timestamp"]
        if not time.time() - ts > 5:
            raise forms.ValidationError("Timestamp check failed")
        return ts

    # etc...

这很好用。但是还有一个问题:用户第一次提交表单时会检查时间戳,我需要避免这种情况

有解决办法吗?

谢谢! :-)

【问题讨论】:

  • 你为什么不在用户的会话中记录这个?
  • 我认为 session 也是要走的路。

标签: python django forms django-forms timestamp


【解决方案1】:

执行此操作的一种方法是将initial 值设置为时间,假设为 0,并在表单验证后将其更新为当前时间戳,并且仅在它不为 0 时检查时间戳:

class MyForm(forms.Form):
    timestamp     = forms.IntegerField(widget=forms.HiddenInput, initial=0)
    #look at the initial = 0

    security_hash = forms.CharField(min_length=40, max_length=40, widget=forms.HiddenInput)


    def clean_timestamp(self):
        """Make sure the delay is over (5 seconds)."""
        ts = self.cleaned_data["timestamp"]
        if timestamp != 0 and not time.time() - ts > 5:
            raise forms.ValidationError("Timestamp check failed")
        return ts

    def clean(self):
        cleaned_data = self.cleaned_data
        if len(self._errors) == 0: #it validates
            cleaned_data["timestamp"] = time.time()
        return cleaned_data

另一种可能的解决方案是使用sessions。它更安全,但不是防弹的。使用以前的方法,用户可以多次发送相同的帖子数据,并且表单将验证多次(因为他发送的是相同的时间戳)。对于会话,您需要用户启用 cookie,但他们将无法发送验证速度快于 5 秒的帖子数据。

这样,一旦发生正确的表单提交,您就可以将时间保存在用户的会话密钥中,并在重新验证表单之前进行检查。这很容易在视图中完成。如果您想在表单逻辑级别执行此操作,则需要在接受请求的表单中创建自己的干净方法(以便您可以使用会话)。请注意,用户可以清理他的 cookie 并作为“新”用户发布。

希望这会有所帮助。

【讨论】:

  • 我没有考虑过使用用户的会话。谢谢:-)
【解决方案2】:

用户第一次提交表单时会检查时间戳,我需要避免这种情况。

如果这是问题所在,您不能创建设置时间戳 -5 分钟的表单吗?

【讨论】:

    猜你喜欢
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    相关资源
    最近更新 更多