form.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. from __future__ import unicode_literals
  2. from wtforms.form import Form
  3. from wtforms.validators import ValidationError
  4. from .fields import CSRFTokenField
  5. class SecureForm(Form):
  6. """
  7. Form that enables CSRF processing via subclassing hooks.
  8. """
  9. csrf_token = CSRFTokenField()
  10. def __init__(self, formdata=None, obj=None, prefix='', csrf_context=None, **kwargs):
  11. """
  12. :param csrf_context:
  13. Optional extra data which is passed transparently to your
  14. CSRF implementation.
  15. """
  16. super(SecureForm, self).__init__(formdata, obj, prefix, **kwargs)
  17. self.csrf_token.current_token = self.generate_csrf_token(csrf_context)
  18. def generate_csrf_token(self, csrf_context):
  19. """
  20. Implementations must override this to provide a method with which one
  21. can get a CSRF token for this form.
  22. A CSRF token should be a string which can be generated
  23. deterministically so that on the form POST, the generated string is
  24. (usually) the same assuming the user is using the site normally.
  25. :param csrf_context:
  26. A transparent object which can be used as contextual info for
  27. generating the token.
  28. """
  29. raise NotImplementedError()
  30. def validate_csrf_token(self, field):
  31. """
  32. Override this method to provide custom CSRF validation logic.
  33. The default CSRF validation logic simply checks if the recently
  34. generated token equals the one we received as formdata.
  35. """
  36. if field.current_token != field.data:
  37. raise ValidationError(field.gettext('Invalid CSRF Token'))
  38. @property
  39. def data(self):
  40. d = super(SecureForm, self).data
  41. d.pop('csrf_token')
  42. return d