csrf.py 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. from pathlib import Path
  2. from django.conf import settings
  3. from django.http import HttpResponseForbidden
  4. from django.template import Context, Engine, TemplateDoesNotExist, loader
  5. from django.utils.translation import gettext as _
  6. from django.utils.version import get_docs_version
  7. CSRF_FAILURE_TEMPLATE_NAME = "403_csrf.html"
  8. def builtin_template_path(name):
  9. """
  10. Return a path to a builtin template.
  11. Avoid calling this function at the module level or in a class-definition
  12. because __file__ may not exist, e.g. in frozen environments.
  13. """
  14. return Path(__file__).parent / "templates" / name
  15. def csrf_failure(request, reason="", template_name=CSRF_FAILURE_TEMPLATE_NAME):
  16. """
  17. Default view used when request fails CSRF protection
  18. """
  19. from django.middleware.csrf import REASON_NO_CSRF_COOKIE, REASON_NO_REFERER
  20. c = {
  21. "title": _("Forbidden"),
  22. "main": _("CSRF verification failed. Request aborted."),
  23. "reason": reason,
  24. "no_referer": reason == REASON_NO_REFERER,
  25. "no_referer1": _(
  26. "You are seeing this message because this HTTPS site requires a "
  27. "“Referer header” to be sent by your web browser, but none was "
  28. "sent. This header is required for security reasons, to ensure "
  29. "that your browser is not being hijacked by third parties."
  30. ),
  31. "no_referer2": _(
  32. "If you have configured your browser to disable “Referer” headers, "
  33. "please re-enable them, at least for this site, or for HTTPS "
  34. "connections, or for “same-origin” requests."
  35. ),
  36. "no_referer3": _(
  37. 'If you are using the <meta name="referrer" '
  38. 'content="no-referrer"> tag or including the “Referrer-Policy: '
  39. "no-referrer” header, please remove them. The CSRF protection "
  40. "requires the “Referer” header to do strict referer checking. If "
  41. "you’re concerned about privacy, use alternatives like "
  42. '<a rel="noreferrer" …> for links to third-party sites.'
  43. ),
  44. "no_cookie": reason == REASON_NO_CSRF_COOKIE,
  45. "no_cookie1": _(
  46. "You are seeing this message because this site requires a CSRF "
  47. "cookie when submitting forms. This cookie is required for "
  48. "security reasons, to ensure that your browser is not being "
  49. "hijacked by third parties."
  50. ),
  51. "no_cookie2": _(
  52. "If you have configured your browser to disable cookies, please "
  53. "re-enable them, at least for this site, or for “same-origin” "
  54. "requests."
  55. ),
  56. "DEBUG": settings.DEBUG,
  57. "docs_version": get_docs_version(),
  58. "more": _("More information is available with DEBUG=True."),
  59. }
  60. try:
  61. t = loader.get_template(template_name)
  62. except TemplateDoesNotExist:
  63. if template_name == CSRF_FAILURE_TEMPLATE_NAME:
  64. # If the default template doesn't exist, use the fallback template.
  65. with builtin_template_path("csrf_403.html").open(encoding="utf-8") as fh:
  66. t = Engine().from_string(fh.read())
  67. c = Context(c)
  68. else:
  69. # Raise if a developer-specified template doesn't exist.
  70. raise
  71. return HttpResponseForbidden(t.render(c))