.. _ref-contrib-csrf: ===================================== Cross Site Request Forgery protection ===================================== .. module:: django.contrib.csrf :synopsis: Protects against Cross Site Request Forgeries The CSRF middleware and template tag provides easy-to-use protection against `Cross Site Request Forgeries`_. This type of attack occurs when a malicious Web site creates a link or form button that is intended to perform some action on your Web site, using the credentials of a logged-in user who is tricked into clicking on the link in their browser. The first defense against CSRF attacks is to ensure that GET requests are side-effect free. POST requests can then be protected by adding these middleware into your list of installed middleware following the steps below. .. versionadded:: 1.1 The 'contrib' apps, including the admin, depend on the functionality described here. Anyone upgrading from earlier versions should read the `Upgrading notes`_ carefully. .. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF How to use it ============= .. versionchanged:: 1.1 The template tag functionality (the recommended way to use this) was added in version 1.1. The previous method (still available) is described under `Legacy method`_. To enable CSRF protection for your views, follow these steps: 1. Add the middleware ``'django.contrib.csrf.middleware.CsrfViewMiddleware'`` to your list of middleware classes, :setting:`MIDDLEWARE_CLASSES`. (Currently it can come anywhere in the list with respect to other middleware included in Django. It should come before any view middleware that assume that CSRF attacks have been dealt with.) 2. Add ``'django.contrib.csrf'`` to your :setting:`INSTALLED_APPS`. 3. In any template that uses a POST form, first load the 'csrf' template tag library:: {% load csrf %} Then use the ``csrf_token`` tag inside the ``
`` element, e.g.:: {% csrf_token %} 4. In the corresponding view functions, ensure that the ``'django.contrib.csrf.context_processors.csrf'`` is being used. Usually, this can be done in one of two ways: 1. Using RequestContext: 1. Ensure ``'django.contrib.csrf.context_processors.csrf'`` is present in your :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting. It is present by default. 2. Use ``RequestContext`` as the context instance in the relevant views. If you are using generic views or contrib apps, you are covered already. 2. Manually import and use the processor to generate the CSRF token and add it to the template context. e.g.:: from django.contrib.csrf.context_processors import csrf from django.template import Context from django.shortcuts import render_to_response def my_view(request): c = Context() c.update(csrf(request)) return render_to_response("a_template.html", context_instance=c) 5. Ensure that any code in a view which could create a new session executes **before** any templates containing a ``csrf_token`` tag are rendered. Note that sessions can be created implicitly simply by setting a value or accessing the contents. If this is done after the template is rendered, the CSRF token it contains could be incorrect, and the following form submission will be rejected. Legacy method ------------- In Django 1.0, the template tag did not exist. Instead, a post-processing middleware that re-wrote POST forms to include the CRSF token was used. If you are upgrading a site from version 1.0 or earlier, please read this section and the `Upgrading notes`_ below. The post-processing middleware is still available as ``CsrfResponseMiddleware``, and it can be used by following these steps: 1. Follow step 1 above to install ``CsrfViewMiddleware``. 2. Add ``'django.contrib.csrf.middleware.CsrfResponseMiddleware'`` to your :setting:`MIDDLEWARE_CLASSES` setting. ``CsrfResponseMiddleware`` needs to process the response after the ``SessionMiddleware``, so must come before it in the list. It also must process the response before things like compression happen to the response, so it must come after ``GZipMiddleware`` in the list. Use of the ``CsrfResponseMiddleware`` is not recommended, but it can be used as an interim measure until applications have been updated to use the ``{% crsf_token %}`` tag. Django 1.0 provided a single ``CsrfMiddleware`` class. This is also still available for backwards compatibility. It combines the functions of the two new middleware. Upgrading notes --------------- When upgrading to version 1.1 or later, you may have applications that rely on the old post-processing functionality for CSRF protection, or you may not have enabled any CSRF protection. This section outlines the steps necessary for a smooth upgrade, without having to fix all the applications to use the new template tag method immediately. If you are using any of the contrib apps (such as the admin), there are some required steps for these applications to continue working. First, the CSRF application must be added to :setting:`INSTALLED_APPS` (See `How to use it`_ above, step 2). Second, the :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting must be updated (step 4.1.1 above). If you have ``CsrfMiddleware`` in your :setting:`MIDDLEWARE_CLASSES`, you will now have a working installation with CSRF protection. It is recommended at this point that you replace ``CsrfMiddleware`` with its two components, ``CsrfViewMiddleware`` and ``CsrfResponseMiddleware``. If you do not have any of the the middleware in your :setting:`MIDDLEWARE_CLASSES`, you will have a working installation but without any CSRF protection (just as you had before). It is recommended to install ``CsrfViewMiddleware`` and ``CsrfResponseMiddleware``, but if you are not interested in having any CSRF protection, you can simply stop here. Assuming you have followed the above, all views in your Django site will now be protected by the ``CsrfViewMiddleware``. Contrib apps meet the requirements imposed by the ``CsrfViewMiddleware`` using the template tag, and other applications in your project will meet its requirements by virtue of the ``CsrfResponseMiddleware``. The next step is to update all your applications to use the template tag, as described in `How to use it`_, steps 3-5. This can be done as soon as is practical. Any applications that are updated will now require Django 1.1 or later, since they will use the CSRF template tag library which was not available in earlier versions. Finally, once all applications are upgraded, the ``CsrfResponseMiddleware`` can be removed. While in the process of upgrading, the ``csrf_response_exempt`` decorator, described in `Exceptions`_, may be useful. The post-processing middleware imposes a performance hit, and any views that have been upgraded to use the new template tag method no longer need it. Using this decorator will allow you to avoid this performance hit. Exceptions ---------- .. versionadded:: 1.1 To manually exclude a view function from being handled by either of the two CSRF middleware, you can use the ``csrf_exempt`` decorator, found in the ``django.contrib.csrf.middleware`` module. For example:: from django.contrib.csrf.middleware import csrf_exempt def my_view(request): return HttpResponse('Hello world') my_view = csrf_exempt(my_view) Like the middleware, the ``csrf_exempt`` decorator is composed of two parts: a ``csrf_view_exempt`` decorator and a ``csrf_response_exempt`` decorator, found in the same module. These disable the view protection mechanism (``CsrfViewMiddleware``) and the response post-processing (``CsrfResponseMiddleware``) respectively. They can be used individually if required. You don't have to worry about doing this for most AJAX views. Any request sent with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the next section.) Rejected requests ================= By default, a '403 Forbidden' response is sent to the user if an incoming request fails the checks performed by ``CsrfViewMiddleware``. This should usually only be seen when there is a genuine Cross Site Request Forgery, or when, due to a programming error, the CSRF token has not been included with a POST form. No logging is done, and the error message is not very friendly, so you may want to provide your own page for handling this condition. To do this, simply set the :setting:`CSRF_FAILURE_VIEW` setting to a dotted path to your own view function. How it works ============ The CSRF protection requires two things: 1. A hidden form field with the name 'csrfmiddlewaretoken' must be added to all outgoing POST forms. The value of this field is a hash of the session ID plus a secret. If there is no session ID set, this modification of the response isn't done, so there is very little performance penalty for those requests that don't have a session. This part is done by the template tag (and with the legacy method, it is done by ``CsrfResponseMiddleware``). 2. On all incoming POST requests that have the session cookie set, the 'csrfmiddlewaretoken' must be present and correct. If it isn't, the user will get a 403 error. This check is done by ``CsrfViewMiddleware``. This ensures that only forms that have originated from your Web site can be used to POST data back. It deliberately only targets HTTP POST requests (and the corresponding POST forms). GET requests ought never to have any potentially dangerous side effects (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a CSRF attack with a GET request ought to be harmless. POST requests that are not accompanied by a session cookie are not protected, but they do not need to be protected, since the 'attacking' Web site could make these kind of requests anyway. The Content-Type is checked before modifying the response, and only pages that are served as 'text/html' or 'application/xml+xhtml' are modified. The middleware tries to be smart about requests that come in via AJAX. Many JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP header; these requests are detected and automatically *not* handled by this middleware. We can do this safely because, in the context of a browser, the header can only be added by using ``XMLHttpRequest``, and browsers already implement a same-domain policy for ``XMLHttpRequest``. (Note that this is not secure if you don't trust content within the same domain or subdomains.) .. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html Limitations =========== These middleware require Django's session framework to work. If you have a custom authentication system that manually sets cookies and the like, it won't help you. If you are using ``CsrfResponseMiddleware`` and your app creates HTML pages and forms in some unusual way, (e.g. it sends fragments of HTML in JavaScript document.write statements) you might bypass the filter that adds the hidden field to the form, in which case form submission will always fail. It may still be possible to use the middleware, provided you can find some way to get the CSRF token and ensure that is included when your form is submitted.