csrf.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. from django.conf import settings
  2. from django.http import HttpResponseForbidden
  3. from django.template import Context, Template
  4. from django.utils.translation import ugettext as _
  5. # We include the template inline since we need to be able to reliably display
  6. # this error message, especially for the sake of developers, and there isn't any
  7. # other way of making it available independent of what is in the settings file.
  8. # Only the text appearing with DEBUG=False is translated. Normal translation
  9. # tags cannot be used with this inline templates as makemessages would not be
  10. # able to discover the strings.
  11. CSRF_FAILURE_TEMPLATE = """
  12. <!DOCTYPE html>
  13. <html lang="en">
  14. <head>
  15. <meta http-equiv="content-type" content="text/html; charset=utf-8">
  16. <meta name="robots" content="NONE,NOARCHIVE">
  17. <title>403 Forbidden</title>
  18. <style type="text/css">
  19. html * { padding:0; margin:0; }
  20. body * { padding:10px 20px; }
  21. body * * { padding:0; }
  22. body { font:small sans-serif; background:#eee; }
  23. body>div { border-bottom:1px solid #ddd; }
  24. h1 { font-weight:normal; margin-bottom:.4em; }
  25. h1 span { font-size:60%; color:#666; font-weight:normal; }
  26. #info { background:#f6f6f6; }
  27. #info ul { margin: 0.5em 4em; }
  28. #info p, #summary p { padding-top:10px; }
  29. #summary { background: #ffc; }
  30. #explanation { background:#eee; border-bottom: 0px none; }
  31. </style>
  32. </head>
  33. <body>
  34. <div id="summary">
  35. <h1>{{ title }} <span>(403)</span></h1>
  36. <p>{{ main }}</p>
  37. {% if no_referer %}
  38. <p>{{ no_referer1 }}</p>
  39. <p>{{ no_referer2 }}</p>
  40. {% endif %}
  41. {% if no_cookie %}
  42. <p>{{ no_cookie1 }}</p>
  43. <p>{{ no_cookie2 }}</p>
  44. {% endif %}
  45. </div>
  46. {% if DEBUG %}
  47. <div id="info">
  48. <h2>Help</h2>
  49. {% if reason %}
  50. <p>Reason given for failure:</p>
  51. <pre>
  52. {{ reason }}
  53. </pre>
  54. {% endif %}
  55. <p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
  56. <a
  57. href='http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ref-contrib-csrf'>Django's
  58. CSRF mechanism</a> has not been used correctly. For POST forms, you need to
  59. ensure:</p>
  60. <ul>
  61. <li>Your browser is accepting cookies.</li>
  62. <li>The view function uses <a
  63. href='http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext'><code>RequestContext</code></a>
  64. for the template, instead of <code>Context</code>.</li>
  65. <li>In the template, there is a <code>{% templatetag openblock %} csrf_token
  66. {% templatetag closeblock %}</code> template tag inside each POST form that
  67. targets an internal URL.</li>
  68. <li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
  69. <code>csrf_protect</code> on any views that use the <code>csrf_token</code>
  70. template tag, as well as those that accept the POST data.</li>
  71. </ul>
  72. <p>You're seeing the help section of this page because you have <code>DEBUG =
  73. True</code> in your Django settings file. Change that to <code>False</code>,
  74. and only the initial error message will be displayed. </p>
  75. <p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
  76. </div>
  77. {% else %}
  78. <div id="explanation">
  79. <p><small>{{ more }}</small></p>
  80. </div>
  81. {% endif %}
  82. </body>
  83. </html>
  84. """
  85. def csrf_failure(request, reason=""):
  86. """
  87. Default view used when request fails CSRF protection
  88. """
  89. from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE
  90. t = Template(CSRF_FAILURE_TEMPLATE)
  91. c = Context({
  92. 'title': _("Forbidden"),
  93. 'main': _("CSRF verification failed. Request aborted."),
  94. 'reason': reason,
  95. 'no_referer': reason == REASON_NO_REFERER,
  96. 'no_referer1': _(
  97. "You are seeing this message because this HTTPS site requires a "
  98. "'Referer header' to be sent by your Web browser, but none was "
  99. "sent. This header is required for security reasons, to ensure "
  100. "that your browser is not being hijacked by third parties."),
  101. 'no_referer2': _(
  102. "If you have configured your browser to disable 'Referer' headers, "
  103. "please re-enable them, at least for this site, or for HTTPS "
  104. "connections, or for 'same-origin' requests."),
  105. 'no_cookie': reason == REASON_NO_CSRF_COOKIE,
  106. 'no_cookie1': _(
  107. "You are seeing this message because this site requires a CSRF "
  108. "cookie when submitting forms. This cookie is required for "
  109. "security reasons, to ensure that your browser is not being "
  110. "hijacked by third parties."),
  111. 'no_cookie2': _(
  112. "If you have configured your browser to disable cookies, please "
  113. "re-enable them, at least for this site, or for 'same-origin' "
  114. "requests."),
  115. 'DEBUG': settings.DEBUG,
  116. 'more': _("More information is available with DEBUG=True."),
  117. })
  118. return HttpResponseForbidden(t.render(c), content_type='text/html')