Ticket #9977: csrf_template_tag_4.diff

File csrf_template_tag_4.diff, 35.4 KB (added by Luke Plant, 15 years ago)

update docs, contrib apps, refactor, new features

  • django/conf/project_template/settings.py

     
    6060MIDDLEWARE_CLASSES = (
    6161    'django.middleware.common.CommonMiddleware',
    6262    'django.contrib.csrf.middleware.CsrfViewMiddleware',
    63     'django.contrib.csrf.middleware.CsrfResponseMiddleware',
    6463    'django.contrib.sessions.middleware.SessionMiddleware',
    6564    'django.contrib.auth.middleware.AuthenticationMiddleware',
    6665)
     
    7675INSTALLED_APPS = (
    7776    'django.contrib.auth',
    7877    'django.contrib.contenttypes',
     78    'django.contrib.csrf',
    7979    'django.contrib.sessions',
    8080    'django.contrib.sites',
    8181)
  • django/conf/global_settings.py

     
    165165    'django.core.context_processors.debug',
    166166    'django.core.context_processors.i18n',
    167167    'django.core.context_processors.media',
     168    'django.contrib.csrf.context_processors.csrf',
    168169#    'django.core.context_processors.request',
    169170)
    170171
     
    303304MIDDLEWARE_CLASSES = (
    304305#     'django.middleware.gzip.GZipMiddleware',
    305306    'django.contrib.csrf.middleware.CsrfViewMiddleware',
    306     'django.contrib.csrf.middleware.CsrfResponseMiddleware',
    307307    'django.contrib.sessions.middleware.SessionMiddleware',
    308308    'django.contrib.auth.middleware.AuthenticationMiddleware',
    309309#     'django.middleware.http.ConditionalGetMiddleware',
     
    379379# The number of days a password reset link is valid for
    380380PASSWORD_RESET_TIMEOUT_DAYS = 3
    381381
     382########
     383# CSRF #
     384########
     385
     386# Dotted path to callable to be used as view when a request is
     387# rejected by the CSRF middleware.
     388CSRF_FAILURE_VIEW = 'django.contrib.csrf.views.csrf_failure'
     389
    382390###########
    383391# TESTING #
    384392###########
  • django/contrib/formtools/templates/formtools/preview.html

     
    11{% extends "base.html" %}
    2 
     2{% load csrf %}
    33{% block content %}
    44
    55<h1>Preview your submission</h1>
     
    1515
    1616<p>Security hash: {{ hash_value }}</p>
    1717
    18 <form action="" method="post">
     18<form action="" method="post">{% csrf_token %}
    1919{% for field in form %}{{ field.as_hidden }}
    2020{% endfor %}
    2121<input type="hidden" name="{{ stage_field }}" value="2" />
     
    2525
    2626<h1>Or edit it again</h1>
    2727
    28 <form action="" method="post">
     28<form action="" method="post">{% csrf_token %}
    2929<table>
    3030{{ form }}
    3131</table>
  • django/contrib/formtools/templates/formtools/form.html

     
    11{% extends "base.html" %}
    2 
     2{% load csrf %}
    33{% block content %}
    44
    55{% if form.errors %}<h1>Please correct the following errors</h1>{% else %}<h1>Submit</h1>{% endif %}
    66
    7 <form action="" method="post">
     7<form action="" method="post">{% csrf_token %}
    88<table>
    99{{ form }}
    1010</table>
  • django/contrib/comments/templates/comments/approve.html

     
    11{% extends "comments/base.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block title %}{% trans "Approve a comment" %}{% endblock %}
    55
    66{% block content %}
    77  <h1>{% trans "Really make this comment public?" %}</h1>
    88  <blockquote>{{ comment|linebreaks }}</blockquote>
    9   <form action="." method="post">
     9  <form action="." method="post">{% csrf_token %}
    1010    <input type="hidden" name="next" value="{{ next }}" id="next" />
    1111    <p class="submit">
    1212      <input type="submit" name="submit" value="{% trans "Approve" %}" /> or <a href="{{ comment.get_absolute_url }}">cancel</a>
  • django/contrib/comments/templates/comments/preview.html

     
    11{% extends "comments/base.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block title %}{% trans "Preview your comment" %}{% endblock %}
    55
    66{% block content %}
    77  {% load comments %}
    8   <form action="{% comment_form_target %}" method="post">
     8  <form action="{% comment_form_target %}" method="post">{% csrf_token %}
    99    {% if form.errors %}
    1010    <h1>{% blocktrans count form.errors|length as counter %}Please correct the error below{% plural %}Please correct the errors below{% endblocktrans %}</h1>
    1111    {% else %}
  • django/contrib/comments/templates/comments/delete.html

     
    11{% extends "comments/base.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block title %}{% trans "Remove a comment" %}{% endblock %}
    55
    66{% block content %}
    77<h1>{% trans "Really remove this comment?" %}</h1>
    88  <blockquote>{{ comment|linebreaks }}</blockquote>
    9   <form action="." method="post">
     9  <form action="." method="post">{% csrf_token %}
    1010    <input type="hidden" name="next" value="{{ next }}" id="next" />
    1111    <p class="submit">
    1212    <input type="submit" name="submit" value="{% trans "Remove" %}" /> or <a href="{{ comment.get_absolute_url }}">cancel</a>
  • django/contrib/comments/templates/comments/form.html

     
    1 {% load comments i18n %}
    2 <form action="{% comment_form_target %}" method="post">
     1{% load comments i18n csrf %}
     2<form action="{% comment_form_target %}" method="post">{% csrf_token %}
    33  {% for field in form %}
    44    {% if field.is_hidden %}
    55      {{ field }}
  • django/contrib/comments/templates/comments/moderation_queue.html

     
    11{% extends "admin/change_list.html" %}
    2 {% load adminmedia i18n %}
     2{% load adminmedia i18n csrf %}
    33
    44{% block title %}{% trans "Comment moderation queue" %}{% endblock %}
    55
     
    4444      {% for comment in comments %}
    4545        <tr class="{% cycle 'row1' 'row2' %}">
    4646          <td class="actions">
    47             <form action="{% url comments-approve comment.pk %}" method="post">
     47            <form action="{% url comments-approve comment.pk %}" method="post">{% csrf_token %}
    4848              <input type="hidden" name="next" value="{% url comments-moderation-queue %}" />
    4949              <input class="approve submit" type="submit" name="submit" value="{% trans "Approve" %}" />
    5050            </form>
    51             <form action="{% url comments-delete comment.pk %}" method="post">
     51            <form action="{% url comments-delete comment.pk %}" method="post">{% csrf_token %}
    5252              <input type="hidden" name="next" value="{% url comments-moderation-queue %}" />
    5353              <input class="remove submit" type="submit" name="submit" value="{% trans "Remove" %}" />
    5454            </form>
  • django/contrib/comments/templates/comments/flag.html

     
    11{% extends "comments/base.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block title %}{% trans "Flag this comment" %}{% endblock %}
    55
    66{% block content %}
    77<h1>{% trans "Really flag this comment?" %}</h1>
    88  <blockquote>{{ comment|linebreaks }}</blockquote>
    9   <form action="." method="post">
     9  <form action="." method="post">{% csrf_token %}
    1010    <input type="hidden" name="next" value="{{ next }}" id="next" />
    1111    <p class="submit">
    1212    <input type="submit" name="submit" value="{% trans "Flag" %}" /> or <a href="{{ comment.get_absolute_url }}">cancel</a>
  • django/contrib/admin/templates/admin/change_list.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load adminmedia admin_list i18n %}
     2{% load adminmedia admin_list i18n csrf %}
    33
    44{% block extrastyle %}
    55  {{ block.super }}
     
    6464      {% endblock %}
    6565     
    6666      {% if cl.formset %}
    67         <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
     67        <form action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>{% csrf_token %}
    6868        {{ cl.formset.management_form }}
    6969      {% endif %}
    7070
  • django/contrib/admin/templates/admin/template_validator.html

     
    11{% extends "admin/base_site.html" %}
    2 
     2{% load csrf %}
    33{% block content %}
    44
    55<div id="content-main">
    66
    7 <form action="" method="post">
     7<form action="" method="post">{% csrf_token %}
    88
    99{% if form.errors %}
    1010<p class="errornote">Your template had {{ form.errors|length }} error{{ form.errors|pluralize }}:</p>
  • django/contrib/admin/templates/admin/auth/user/change_password.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n admin_modify adminmedia %}
     2{% load i18n admin_modify adminmedia csrf %}
    33{% block extrahead %}{{ block.super }}
    44<script type="text/javascript" src="../../../../jsi18n/"></script>
    55{% endblock %}
     
    1414</div>
    1515{% endif %}{% endblock %}
    1616{% block content %}<div id="content-main">
    17 <form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
     17<form action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %}
    1818<div>
    1919{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
    2020{% if form.errors %}
  • django/contrib/admin/templates/admin/login.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block extrastyle %}{% load adminmedia %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/login.css" />{% endblock %}
    55
     
    1414<p class="errornote">{{ error_message }}</p>
    1515{% endif %}
    1616<div id="content-main">
    17 <form action="{{ app_path }}" method="post" id="login-form">
     17<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
    1818  <div class="form-row">
    1919    <label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
    2020  </div>
  • django/contrib/admin/templates/admin/change_form.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n admin_modify adminmedia %}
     2{% load i18n admin_modify adminmedia csrf %}
    33
    44{% block extrahead %}{{ block.super }}
    55<script type="text/javascript" src="../../../jsi18n/"></script>
     
    2929  </ul>
    3030{% endif %}{% endif %}
    3131{% endblock %}
    32 <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
     32<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% csrf_token %}{% block form_top %}{% endblock %}
    3333<div>
    3434{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
    3535{% if save_on_top %}{% submit_row %}{% endif %}
  • django/contrib/admin/templates/admin/delete_confirmation.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block breadcrumbs %}
    55<div class="breadcrumbs">
     
    2222{% else %}
    2323    <p>{% blocktrans with object as escaped_object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktrans %}</p>
    2424    <ul>{{ deleted_objects|unordered_list }}</ul>
    25     <form action="" method="post">
     25    <form action="" method="post">{% csrf_token %}
    2626    <div>
    2727    <input type="hidden" name="post" value="yes" />
    2828    <input type="submit" value="{% trans "Yes, I'm sure" %}" />
  • django/contrib/admin/templates/registration/password_reset_confirm.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> &rsaquo; {% trans 'Password reset confirmation' %}</div>{% endblock %}
    55
     
    1313
    1414<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
    1515
    16 <form action="" method="post">
     16<form action="" method="post">{% csrf_token %}
    1717{{ form.new_password1.errors }}
    1818<p class="aligned wide"><label for="id_new_password1">{% trans 'New password:' %}</label>{{ form.new_password1 }}</p>
    1919{{ form.new_password2.errors }}
  • django/contrib/admin/templates/registration/password_reset_form.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33
    44{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> &rsaquo; {% trans 'Password reset' %}</div>{% endblock %}
    55
     
    1111
    1212<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>
    1313
    14 <form action="" method="post">
     14<form action="" method="post">{% csrf_token %}
    1515{{ form.email.errors }}
    1616<p><label for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }} <input type="submit" value="{% trans 'Reset my password' %}" /></p>
    1717</form>
  • django/contrib/admin/templates/registration/password_change_form.html

     
    11{% extends "admin/base_site.html" %}
    2 {% load i18n %}
     2{% load i18n csrf %}
    33{% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %} {% trans 'Change password' %} / <a href="../logout/">{% trans 'Log out' %}</a>{% endblock %}
    44{% block breadcrumbs %}<div class="breadcrumbs"><a href="../">{% trans 'Home' %}</a> &rsaquo; {% trans 'Password change' %}</div>{% endblock %}
    55
     
    1111
    1212<p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
    1313
    14 <form action="" method="post">
     14<form action="" method="post">{% csrf_token %}
    1515
    1616{{ form.old_password.errors }}
    1717<p class="aligned wide"><label for="id_old_password">{% trans 'Old password:' %}</label>{{ form.old_password }}</p>
  • django/contrib/csrf/middleware.py

     
    1313    from django.utils.functional import wraps  # Python 2.3, 2.4 fallback.
    1414
    1515from django.conf import settings
    16 from django.http import HttpResponseForbidden
     16from django.core.urlresolvers import get_callable
    1717from django.utils.hashcompat import md5_constructor
    1818from django.utils.safestring import mark_safe
    1919
    20 _ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>')
    21 
    2220_POST_FORM_RE = \
    2321    re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE)
    2422
    2523_HTML_TYPES = ('text/html', 'application/xhtml+xml')
    2624
     25def _get_failure_view():
     26    """
     27    Returns the view to be used for CSRF rejections
     28    """
     29    return get_callable(settings.CSRF_FAILURE_VIEW)
     30
     31def get_token(request):
     32    """
     33    Returns the the CSRF token required for a session,
     34    or None if there is no session active.
     35    """
     36    try:
     37        session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
     38    except KeyError:
     39        # No session
     40        return None
     41
     42    return _make_token(session_id)
     43
    2744def _make_token(session_id):
    2845    return md5_constructor(settings.SECRET_KEY + session_id).hexdigest()
    2946
     
    4057            if request.is_ajax():
    4158                return None
    4259
    43             try:
    44                 session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
    45             except KeyError:
     60            csrf_token = get_token(request)
     61            if csrf_token is None:
    4662                # No session, no check required
    4763                return None
    4864
    49             csrf_token = _make_token(session_id)
    5065            # check incoming token
    5166            try:
    5267                request_csrf_token = request.POST['csrfmiddlewaretoken']
    5368            except KeyError:
    54                 return HttpResponseForbidden(_ERROR_MSG)
     69                return _get_failure_view()(request)
    5570
    5671            if request_csrf_token != csrf_token:
    57                 return HttpResponseForbidden(_ERROR_MSG)
     72                return _get_failure_view()(request)
    5873
    5974        return None
    6075
  • django/contrib/csrf/views.py

     
     1from django.http import HttpResponseForbidden
     2from django.utils.safestring import mark_safe
     3
     4_ERROR_MSG = mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>')
     5
     6def csrf_failure(request):
     7    """
     8    Default view used when request fails CSRF protection
     9    """
     10    return HttpResponseForbidden(_ERROR_MSG)
  • django/contrib/csrf/tests.py

    Property changes on: django/contrib/csrf/views.py
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    33from django.test import TestCase
    44from django.http import HttpRequest, HttpResponse, HttpResponseForbidden
    55from django.contrib.csrf.middleware import CsrfMiddleware, _make_token, csrf_exempt
     6from django.contrib.csrf.context_processors import csrf
    67from django.conf import settings
     8from django.template import RequestContext, Template
    79
    8 
    910def post_form_response():
    1011    resp = HttpResponse(content="""
    1112<html><body><form method="POST"><input type="text" /></form></body></html>
     
    142143        req.META['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
    143144        req2 = CsrfMiddleware().process_view(req, self.get_view(), (), {})
    144145        self.assertEquals(None, req2)
     146
     147    def _context_instance(self, req):
     148        return RequestContext(req, processors=[csrf])
     149
     150    def test_token_node_no_session(self):
     151        """
     152        Check that CsrfTokenNode works when no session active
     153        """
     154        req = self._get_GET_no_session_request()
     155        context = self._context_instance(req)
     156        template = Template("{% load csrf %}{% csrf_token %}")
     157        self.assertEquals(u"", template.render(context))
     158
     159    def test_token_node_no_session(self):
     160        """
     161        Check that CsrfTokenNode works when a session is active
     162        """
     163        req = self._get_GET_session_request()
     164        context = self._context_instance(req)
     165        template = Template("{% load csrf %}{% csrf_token %}")
     166        rendered = template.render(context)
     167        self.assertNotEqual(u"", rendered)
     168        expected = ("name='csrfmiddlewaretoken' value='%s'" % _make_token(self._session_id))
     169        self.failUnless(expected in rendered)
  • django/contrib/csrf/templatetags/csrf.py

     
     1from django import template
     2from django.utils.safestring import mark_safe
     3
     4register = template.Library()
     5
     6class CsrfTokenNode(template.Node):
     7    def render(self, context):
     8        csrf_token = context.get('csrf_token', None)
     9        if csrf_token:
     10            if csrf_token == 'NOTNEEDED':
     11                return mark_safe(u"")
     12            else:
     13                return mark_safe(u"<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='%s' /></div>" % (csrf_token))
     14        else:
     15            # It's very probable that the token is missing because of
     16            # misconfiguration, so we raise a warning
     17            from django.conf import settings
     18            if settings.DEBUG:
     19                import warnings
     20                warnings.warn("A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not having 'django.contrib.csrf.context_processors.csrf' in TEMPLATE_CONTEXT_PROCESSORS.")
     21            return u''
     22
     23def csrf_token(parser, token):
     24    return CsrfTokenNode()
     25register.tag(csrf_token)
  • django/contrib/csrf/context_processors.py

    Property changes on: django/contrib/csrf/templatetags/csrf.py
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
    
    Property changes on: django/contrib/csrf/templatetags/__init__.py
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
     1from django.contrib.csrf.middleware import get_token
     2
     3def csrf(request):
     4    """
     5    Context processor that provides a CSRF token, or the string
     6    'NOTNEEDED' if it is not needed
     7    """
     8    token = get_token(request)
     9    if token is None:
     10        # In order to be able to provide debugging info in the case of
     11        # misconfiguration, we use a sentinel value instead of an empty
     12        # dict.
     13        return {'csrf_token':'NOTNEEDED'}
     14    else:
     15        return {'csrf_token': token}
     16
  • tests/regressiontests/admin_views/tests.py

    Property changes on: django/contrib/csrf/context_processors.py
    ___________________________________________________________________
    Added: svn:eol-style
       + native
    
     
    745745        # 2 management hidden fields = 2
    746746        # main form submit button = 1
    747747        # search field and search submit button = 2
    748         # 6 + 2 + 1 + 2 = 11 inputs
    749         self.failUnlessEqual(response.content.count("<input"), 11)
     748        # csrf hidden field = 1
     749        # 6 + 2 + 1 + 2 + 1 = 12 inputs
     750        self.failUnlessEqual(response.content.count("<input"), 12)
    750751        # 1 select per object = 3 selects
    751752        self.failUnlessEqual(response.content.count("<select"), 3)
    752753   
  • tests/runtests.py

     
    3030    'django.contrib.sessions',
    3131    'django.contrib.comments',
    3232    'django.contrib.admin',
     33    'django.contrib.csrf',
    3334]
    3435
    3536def get_test_models():
  • docs/ref/contrib/csrf.txt

     
    77.. module:: django.contrib.csrf
    88   :synopsis: Protects against Cross Site Request Forgeries
    99
    10 The CsrfMiddleware classes provides easy-to-use protection against
    11 `Cross Site Request Forgeries`_.  This type of attack occurs when a
    12 malicious Web site creates a link or form button that is intended to
    13 perform some action on your Web site, using the credentials of a
    14 logged-in user who is tricked into clicking on the link in their
    15 browser.
     10The CSRF middleware and template tag provides easy-to-use protection
     11against `Cross Site Request Forgeries`_.  This type of attack occurs
     12when a malicious Web site creates a link or form button that is
     13intended to perform some action on your Web site, using the
     14credentials of a logged-in user who is tricked into clicking on the
     15link in their browser.
    1616
    1717The first defense against CSRF attacks is to ensure that GET requests
    1818are side-effect free.  POST requests can then be protected by adding
    19 these middleware into your list of installed middleware.
     19these middleware into your list of installed middleware following the
     20steps below.
    2021
     22.. versionadded:: 1.1
     23    The functionality described here is depended on by the 'contrib'
     24    apps, including the admin, so usage steps 1, 2 and 4.1.1 below are
     25    **required** for these apps to function.
     26
    2127.. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF
    2228
    2329How to use it
    2430=============
     31.. versionchanged:: 1.1
     32    The template tag functionality (the recommended way to use this)
     33    was added in version 1.1. The previous method (still available) is
     34    described under 'Legacy method'.
    2535
    26 Add the middleware
    27 ``'django.contrib.csrf.middleware.CsrfViewMiddleware'`` and
    28 ``'django.contrib.csrf.middleware.CsrfResponseMiddleware'`` to your
    29 list of middleware classes,
    30 :setting:`MIDDLEWARE_CLASSES`. ``CsrfResponseMiddleware`` needs to
    31 process the response after the ``SessionMiddleware``, so must come
    32 before it in the list.  It also must process the response before
    33 things like compression happen to the response, so it must come after
    34 ``GZipMiddleware`` in the list.
     36Follow these steps:
    3537
    36 The ``CsrfMiddleware`` class, which combines the two classes, is also
    37 available, for backwards compatibility with Django 1.0.
     38    1. Add the middleware
     39       ``'django.contrib.csrf.middleware.CsrfViewMiddleware'`` to your
     40       list of middleware classes, :setting:`MIDDLEWARE_CLASSES`.
    3841
    39 .. versionchanged:: 1.1
    40     previous versions of Django did not provide these two components
    41     of ``CsrfMiddleware`` as described above.
     42    2. Add ``'django.contrib.csrf'`` to your :setting:`INSTALLED_APPS`.
    4243
     44    3. In any template that uses a POST form, first load the 'csrf'
     45       template tag library::
     46
     47           {% load csrf %}
     48
     49       Then use the ``csrf_token`` tag inside the ``<form>`` element, e.g.::
     50
     51           <form action="" method="POST">{% csrf_token %}
     52
     53    4. In the corresponding view functions, ensure that the
     54       ``'django.contrib.csrf.context_processors.csrf'`` is being
     55       used. Usually, this can be done in one of two ways:
     56
     57       1. Using RequestContext:
     58
     59          1. Ensure ``'django.contrib.csrf.context_processors.csrf'``
     60             is present in your :setting:`TEMPLATE_CONTEXT_PROCESSORS`
     61             setting. It is present by default.
     62
     63          2. Use ``RequestContext`` as the context instance in the
     64             relevant views. If you are using generic views or contrib
     65             apps, you are covered already.
     66
     67       2. Manually import and use the processor to generate the CSRF
     68          token and add it to the template context. e.g.::
     69
     70              from django.contrib.csrf.context_processors import csrf
     71              from django.template import Context
     72              from django.shortcuts import render_to_response
     73              def my_view(request):
     74                  c = Context()
     75                  c.update(csrf(request))
     76                  return render_to_response("a_template.html", context_instance=c)
     77
     78    5. Ensure that any views which create a new session do not in the
     79       same response present a POST form.  Often this is achieved by
     80       doing a redirect.
     81
     82       The reason for this is as follows: the CSRF
     83       token that is inserted by the ``csrf_token`` tag is calculated
     84       on the basis of the ID of an existing session (which is known
     85       from the cookies attached to the request).  When a new session
     86       is created, only the outgoing response object is affected,
     87       which the template tag does not have access to, so the template
     88       tag would produce an incorrect token in this case, resulting in
     89       an error when the user tries to submit the form.
     90
     91Legacy method
     92-------------
     93
     94In Django 1.0, the template tag did not exist.  Instead, a
     95post-processing middleware that re-wrote POST forms to include the
     96CRSF token was used.  This is still available as
     97``CsrfResponseMiddleware``, and it can be used by following these
     98steps:
     99
     100    1. Follow step 1 above to install ``CsrfViewMiddleware``.
     101
     102    2. Add ``'django.contrib.csrf.middleware.CsrfResponseMiddleware'``
     103       to your :setting:`MIDDLEWARE_CLASSES` setting.
     104
     105       ``CsrfResponseMiddleware`` needs to process the response after
     106       the ``SessionMiddleware``, so must come before it in the list.
     107       It also must process the response before things like
     108       compression happen to the response, so it must come after
     109       ``GZipMiddleware`` in the list.
     110
     111Use of the ``CsrfResponseMiddleware`` is not recommended, but it can
     112be used as an interim measure until applications have been updated to use
     113the ``{% crsf_token %}`` tag.
     114
     115Django 1.0 provided a single ``CsrfMiddleware`` class.  This is also
     116still available for backwards compatibility.  It combines the
     117functions of the two new middleware.
     118
     119
    43120Exceptions
    44121----------
    45122
     
    66143request sent with "X-Requested-With: XMLHttpRequest" is automatically
    67144exempt. (See the next section.)
    68145
     146Rejected requests
     147=================
     148
     149By default, when an incoming request fails the checks that
     150``CsrfViewMiddleware`` performs, a '403 Forbidden' response is sent to
     151the user.  This should only be seen usually when there is a genuine
     152Cross Site Request Forgery, or when due to a programmer error the CSRF
     153token has not been included with a POST form.
     154
     155No logging is done, and the error message is not very friendly, so you
     156may want to provide your own page for handling this condition.  To do
     157this, simply set the :setting:`CSRF_FAILURE_VIEW` setting to a dotted
     158path to your own view function.
     159
    69160How it works
    70161============
    71162
    72 The CSRF middleware do two things:
     163The CSRF protection requires two things:
    73164
    74 1. It modifies outgoing requests by adding a hidden form field to all
    75    'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is
    76    a hash of the session ID plus a secret. If there is no session ID set,
    77    this modification of the response isn't done, so there is very little
    78    performance penalty for those requests that don't have a session.
    79    (This is done by ``CsrfResponseMiddleware``).
     1651. A hidden form field with the name 'csrfmiddlewaretoken' must be
     166   added to all outgoing POST forms.  The value of this field is a
     167   hash of the session ID plus a secret. If there is no session ID
     168   set, this modification of the response isn't done, so there is very
     169   little performance penalty for those requests that don't have a
     170   session.
    80171
    81 2. On all incoming POST requests that have the session cookie set, it
    82    checks that the 'csrfmiddlewaretoken' is present and correct. If it
    83    isn't, the user will get a 403 error. (This is done by
    84    ``CsrfViewMiddleware``)
     172   This part is done by the template tag (and with the
     173   legacy method, it is done by ``CsrfResponseMiddleware``).
    85174
     1752. On all incoming POST requests that have the session cookie set, the
     176   'csrfmiddlewaretoken' must be present and correct. If it isn't, the
     177   user will get a 403 error.
     178
     179   This check is done by ``CsrfViewMiddleware``.
     180
    86181This ensures that only forms that have originated from your Web site
    87182can be used to POST data back.
    88183
     
    117212have a custom authentication system that manually sets cookies and the
    118213like, it won't help you.
    119214
    120 If your app creates HTML pages and forms in some unusual way, (e.g.
    121 it sends fragments of HTML in JavaScript document.write statements)
    122 you might bypass the filter that adds the hidden field to the form,
    123 in which case form submission will always fail.  It may still be possible
    124 to use the middleware, provided you can find some way to get the
    125 CSRF token and ensure that is included when your form is submitted.
     215If you are using ``CsrfResponseMiddleware`` and your app creates HTML
     216pages and forms in some unusual way, (e.g.  it sends fragments of HTML
     217in JavaScript document.write statements) you might bypass the filter
     218that adds the hidden field to the form, in which case form submission
     219will always fail.  It may still be possible to use the middleware,
     220provided you can find some way to get the CSRF token and ensure that
     221is included when your form is submitted.
  • docs/ref/settings.txt

     
    146146
    147147.. setting:: DATABASE_ENGINE
    148148
     149CSRF_FAILURE_VIEW
     150-----------------
     151
     152Default: ``'django.contrib.csrf.views.csrf_failure'``
     153
     154The name of the view function to be used when an incoming request
     155is rejected by the CSRF protection. See :ref:`ref-contrib-csrf`.
     156
    149157DATABASE_ENGINE
    150158---------------
    151159
Back to Top