Hi all,
The patch has been added to:
http://code.djangoproject.com/ticket/9977
It includes tests, docs etc - I think it is complete. Other notes are
below (some of this would need to be prominently noted in the release
notes).
I don't know if this is too late for the beta. Since I guess we are
working on US time, and I'm GMT, I'm guessing I may to have to leave
this to one of the other committers. I'll check email before midnight
GMT and hang out on IRC.
Outline
=======
The approach:
- add a template tag to all POST forms. This requires loading the
csrf template tag library, and also requires using a context
processor to get the token.
- use CsrfViewMiddleware to filter out requests that don't have the
token.
All existing contrib apps use RequestContext, which has made the
changes to them minimal (template only, and settings update).
Thanks to bthomas, Rob Hudson for initial patch.
Testing done
============
I've added tests for template tag etc., there was already pretty
exhaustive testing for the middleware.
The middleware is not enabled for the test suite, so shouldn't cause
any complications.
I've manually tested some views in the admin, but I haven't tested all
the contrib apps, because of the time it would take to set up a
harness for testing them. I believe the existing test suite should
have caught any basic rendering errors in the templates due to typos.
The biggest problem might be that some contrib views don't actually
use RequestContext (I think I checked this, but may have missed some).
Other features
==============
When the middleware rejects a request, you can completely customise
the page that is sent back (goodbye to the unfriendly '403 Forbidden'
page), by setting the CSRF_FAILURE_VIEW setting to provide your custom
view.
Upgrading
=========
Unlike what was committed last week, this patch *requires* changes to
project settings in order for the admin (and other contrib apps) not
to break. It could be considered backwards incompatible for this
reason, but it is not an *API* change, just changes to settings.
The following things must be done:
- django.contrib.csrf added to INSTALLED_APPS (for template tag)
- django.contrib.csrf.middleware.CsrfViewMiddleware added to
MIDDLEWARE_CLASSES (or the existing CsrfMiddleware replaced with
CsrfViewMiddleware)
- django.contrib.csrf.context_processors.csrf added to
TEMPLATE_CONTEXT_PROCESSORS
- Any existing apps should be upgraded to use the {% csrf_token %}
method. Alternatively (but not recommended), the existing
CsrfMiddleware or CsrfResponseMiddleware can be used to cover those
apps.
- Obviously (but worth mentioning), if people have overridden
the affected templates for any contrib apps, they may need
updating. This could be quite a bit of work in some cases, I
imagine. I think that the above solution of using
CsrfResponseMiddleware until the updates are done will also
work in this case.
I don't think the above is that complicated, and compared to the
alternatives that have been proposed, the changes are far less
intrusive. But obviously things can go wrong. To see the impact of
various mistakes, I've outlined a number of scenarios below, it's up
to you to decide how serious these things are. But if we don't do it
now, we'll have to either suffer the existing response re-writing or
have the admin vulnerable to CSRF by default for *another* release.
Scenario 1
----------
Developer doesn't bother to read release notes and do any of the above
updates.
Result: admin app and other contrib apps break immediately (i.e.
templates won't render), due to lack of 'django.contrib.csrf' in
INSTALLED_APPS, causing {% load csrf %} to fail.
Scenario 2
----------
Developer adds django.contrib.csrf to INSTALLED_APPS, but doesn't add
the csrf context processor to TEMPLATE_CONTEXT_PROCESSORS.
Result: the admin app (etc.) will break - it will render, but you will
get 403s if you make any POST requests. If DEBUG = True, the
developer will get a warning informing him of the problem.
Scenario 3
----------
As in (2), but the developer has 'CsrfMiddleware' or
'CsrfResponseMiddleware' installed. This might be accidental, or
because the developer needs the response re-writing middleware for
other apps.
Result: admin etc. will work fine. If DEBUG = True, the developer
will get a warning informing him of the problem.
Scenario 4
----------
The developer adds all settings correctly but doesn't remove
CsrfMiddleware/CsrfResponseMiddleware.
This might be accidental, or because the developer needs the response
re-writing middleware for other apps.
Result: admin will work fine. The CSRF token will get inserted twice,
but this is harmless (it's not even invalid HTML).
(We could fix the double insertions and performance hit by adding
@csrf_response_exempt to relevant views in contrib, if we thought it
was worth it).
Scenario 5
----------
The developer installs all settings apart from adding
'CsrfViewMiddleware'.
Result: no crashes, but no CSRF protection.
Scenario 6
----------
Developer updates all settings correctly, but doesn't upgrade any
other apps to use {% csrf_token %}.
Result: Those apps will break -- users will get 403's when trying to
use POST forms.
--------------
Luke