mirror of
https://github.com/django/django.git
synced 2025-01-30 03:59:19 +00:00
8e70cef9b6
This is a large change to CSRF protection for Django. It includes: * removing the dependency on the session framework. * deprecating CsrfResponseMiddleware, and replacing with a core template tag. * turning on CSRF protection by default by adding CsrfViewMiddleware to the default value of MIDDLEWARE_CLASSES. * protecting all contrib apps (whatever is in settings.py) using a decorator. For existing users of the CSRF functionality, it should be a seamless update, but please note that it includes DEPRECATION of features in Django 1.1, and there are upgrade steps which are detailed in the docs. Many thanks to 'Glenn' and 'bthomas', who did a lot of the thinking and work on the patch, and to lots of other people including Simon Willison and Russell Keith-Magee who refined the ideas. Details of the rationale for these changes is found here: http://code.djangoproject.com/wiki/CsrfProtection As of this commit, the CSRF code is mainly in 'contrib'. The code will be moved to core in a separate commit, to make the changeset as readable as possible. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11660 bcc190cf-cafb-0310-a4f2-bffc1f526a37
181 lines
7.5 KiB
Plaintext
181 lines
7.5 KiB
Plaintext
.. _topics-http-middleware:
|
|
|
|
==========
|
|
Middleware
|
|
==========
|
|
|
|
Middleware is a framework of hooks into Django's request/response processing.
|
|
It's a light, low-level "plugin" system for globally altering Django's input
|
|
and/or output.
|
|
|
|
Each middleware component is responsible for doing some specific function. For
|
|
example, Django includes a middleware component, ``XViewMiddleware``, that adds
|
|
an ``"X-View"`` HTTP header to every response to a ``HEAD`` request.
|
|
|
|
This document explains how middleware works, how you activate middleware, and
|
|
how to write your own middleware. Django ships with some built-in middleware
|
|
you can use right out of the box; they're documented in the :ref:`built-in
|
|
middleware reference <ref-middleware>`.
|
|
|
|
Activating middleware
|
|
=====================
|
|
|
|
To activate a middleware component, add it to the :setting:`MIDDLEWARE_CLASSES`
|
|
list in your Django settings. In :setting:`MIDDLEWARE_CLASSES`, each middleware
|
|
component is represented by a string: the full Python path to the middleware's
|
|
class name. For example, here's the default :setting:`MIDDLEWARE_CLASSES`
|
|
created by :djadmin:`django-admin.py startproject <startproject>`::
|
|
|
|
MIDDLEWARE_CLASSES = (
|
|
'django.middleware.common.CommonMiddleware',
|
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
'django.contrib.csrf.middleware.CsrfViewMiddleware',
|
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
)
|
|
|
|
During the request phases (:meth:`process_request` and :meth:`process_view`
|
|
middleware), Django applies middleware in the order it's defined in
|
|
:setting:`MIDDLEWARE_CLASSES`, top-down. During the response phases
|
|
(:meth:`process_response` and :meth:`process_exception` middleware), the
|
|
classes are applied in reverse order, from the bottom up. You can think of it
|
|
like an onion: each middleware class is a "layer" that wraps the view:
|
|
|
|
.. image:: _images/middleware.png
|
|
:width: 502
|
|
:height: 417
|
|
:alt: Middleware application order.
|
|
|
|
A Django installation doesn't require any middleware -- e.g.,
|
|
:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like -- but it's strongly
|
|
suggested that you at least use
|
|
:class:`~django.middleware.common.CommonMiddleware`.
|
|
|
|
Writing your own middleware
|
|
===========================
|
|
|
|
Writing your own middleware is easy. Each middleware component is a single
|
|
Python class that defines one or more of the following methods:
|
|
|
|
.. _request-middleware:
|
|
|
|
``process_request``
|
|
-------------------
|
|
|
|
.. method:: process_request(self, request)
|
|
|
|
``request`` is an :class:`~django.http.HttpRequest` object. This method is
|
|
called on each request, before Django decides which view to execute.
|
|
|
|
``process_request()`` should return either ``None`` or an
|
|
:class:`~django.http.HttpResponse` object. If it returns ``None``, Django will
|
|
continue processing this request, executing any other middleware and, then, the
|
|
appropriate view. If it returns an :class:`~django.http.HttpResponse` object,
|
|
Django won't bother calling ANY other request, view or exception middleware, or
|
|
the appropriate view; it'll return that :class:`~django.http.HttpResponse`.
|
|
Response middleware is always called on every response.
|
|
|
|
.. _view-middleware:
|
|
|
|
``process_view``
|
|
----------------
|
|
|
|
.. method:: process_view(self, request, view_func, view_args, view_kwargs)
|
|
|
|
``request`` is an :class:`~django.http.HttpRequest` object. ``view_func`` is
|
|
the Python function that Django is about to use. (It's the actual function
|
|
object, not the name of the function as a string.) ``view_args`` is a list of
|
|
positional arguments that will be passed to the view, and ``view_kwargs`` is a
|
|
dictionary of keyword arguments that will be passed to the view. Neither
|
|
``view_args`` nor ``view_kwargs`` include the first view argument
|
|
(``request``).
|
|
|
|
``process_view()`` is called just before Django calls the view. It should
|
|
return either ``None`` or an :class:`~django.http. HttpResponse` object. If it
|
|
returns ``None``, Django will continue processing this request, executing any
|
|
other ``process_view()`` middleware and, then, the appropriate view. If it
|
|
returns an :class:`~django.http. HttpResponse` object, Django won't bother
|
|
calling ANY other request, view or exception middleware, or the appropriate
|
|
view; it'll return that :class:`~django.http. HttpResponse`. Response
|
|
middleware is always called on every response.
|
|
|
|
.. _response-middleware:
|
|
|
|
``process_response``
|
|
--------------------
|
|
|
|
.. method:: process_response(self, request, response)
|
|
|
|
``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the
|
|
:class:`~django.http. HttpResponse` object returned by a Django view.
|
|
|
|
``process_response()`` must return an :class:`~django.http. HttpResponse`
|
|
object. It could alter the given ``response``, or it could create and return a
|
|
brand-new :class:`~django.http. HttpResponse`.
|
|
|
|
Unlike the ``process_request()`` and ``process_view()`` methods, the
|
|
``process_response()`` method is always called, even if the ``process_request()``
|
|
and ``process_view()`` methods of the same middleware class were skipped because
|
|
an earlier middleware method returned an :class:`~django.http. HttpResponse`
|
|
(this means that your ``process_response()`` method cannot rely on setup done in
|
|
``process_request()``, for example). In addition, during the response phase the
|
|
classes are applied in reverse order, from the bottom up. This means classes
|
|
defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first.
|
|
|
|
.. _exception-middleware:
|
|
|
|
``process_exception``
|
|
---------------------
|
|
|
|
.. method:: process_exception(self, request, exception)
|
|
|
|
``request`` is an :class:`~django.http.HttpRequest` object. ``exception`` is an
|
|
``Exception`` object raised by the view function.
|
|
|
|
Django calls ``process_exception()`` when a view raises an exception.
|
|
``process_exception()`` should return either ``None`` or an
|
|
:class:`~django.http. HttpResponse` object. If it returns an
|
|
:class:`~django.http. HttpResponse` object, the response will be returned to
|
|
the browser. Otherwise, default exception handling kicks in.
|
|
|
|
Again, middleware are run in reverse order during the response phase, which
|
|
includes ``process_exception``. If an exception middleware return a response,
|
|
the middleware classes above that middleware will not be called at all.
|
|
|
|
``__init__``
|
|
------------
|
|
|
|
Most middleware classes won't need an initializer since middleware classes are
|
|
essentially placeholders for the ``process_*`` methods. If you do need some
|
|
global state you may use ``__init__`` to set up. However, keep in mind a couple
|
|
of caveats:
|
|
|
|
* Django initializes your middleware without any arguments, so you can't
|
|
define ``__init__`` as requiring any arguments.
|
|
|
|
* Unlike the ``process_*`` methods which get called once per request,
|
|
``__init__`` gets called only *once*, when the web server starts up.
|
|
|
|
Marking middleware as unused
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
It's sometimes useful to determine at run-time whether a piece of middleware
|
|
should be used. In these cases, your middleware's ``__init__`` method may raise
|
|
``django.core.exceptions.MiddlewareNotUsed``. Django will then remove that
|
|
piece of middleware from the middleware process.
|
|
|
|
Guidelines
|
|
----------
|
|
|
|
* Middleware classes don't have to subclass anything.
|
|
|
|
* The middleware class can live anywhere on your Python path. All Django
|
|
cares about is that the :setting:`MIDDLEWARE_CLASSES` setting includes
|
|
the path to it.
|
|
|
|
* Feel free to look at :ref:`Django's available middleware
|
|
<ref-middleware>` for examples.
|
|
|
|
* If you write a middleware component that you think would be useful to
|
|
other people, contribute to the community! :ref:`Let us know
|
|
<internals-contributing>`, and we'll consider adding it to Django.
|