507 lines
18 KiB
Plaintext
507 lines
18 KiB
Plaintext
==========
|
|
Middleware
|
|
==========
|
|
|
|
.. module:: django.middleware
|
|
:synopsis: Django's built-in middleware classes.
|
|
|
|
This document explains all middleware components that come with Django. For
|
|
information on how to use them and how to write your own middleware, see
|
|
the :doc:`middleware usage guide </topics/http/middleware>`.
|
|
|
|
Available middleware
|
|
====================
|
|
|
|
Cache middleware
|
|
----------------
|
|
|
|
.. module:: django.middleware.cache
|
|
:synopsis: Middleware for the site-wide cache.
|
|
|
|
.. class:: UpdateCacheMiddleware
|
|
|
|
.. class:: FetchFromCacheMiddleware
|
|
|
|
Enable the site-wide cache. If these are enabled, each Django-powered page will
|
|
be cached for as long as the :setting:`CACHE_MIDDLEWARE_SECONDS` setting
|
|
defines. See the :doc:`cache documentation </topics/cache>`.
|
|
|
|
"Common" middleware
|
|
-------------------
|
|
|
|
.. module:: django.middleware.common
|
|
:synopsis: Middleware adding "common" conveniences for perfectionists.
|
|
|
|
.. class:: CommonMiddleware
|
|
|
|
Adds a few conveniences for perfectionists:
|
|
|
|
* Forbids access to user agents in the :setting:`DISALLOWED_USER_AGENTS`
|
|
setting, which should be a list of compiled regular expression objects.
|
|
|
|
* Performs URL rewriting based on the :setting:`APPEND_SLASH` and
|
|
:setting:`PREPEND_WWW` settings.
|
|
|
|
If :setting:`APPEND_SLASH` is ``True`` and the initial URL doesn't end
|
|
with a slash, and it is not found in the URLconf, then a new URL is
|
|
formed by appending a slash at the end. If this new URL is found in the
|
|
URLconf, then Django redirects the request to this new URL. Otherwise,
|
|
the initial URL is processed as usual.
|
|
|
|
For example, ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if
|
|
you don't have a valid URL pattern for ``foo.com/bar`` but *do* have a
|
|
valid pattern for ``foo.com/bar/``.
|
|
|
|
If :setting:`PREPEND_WWW` is ``True``, URLs that lack a leading "www."
|
|
will be redirected to the same URL with a leading "www."
|
|
|
|
Both of these options are meant to normalize URLs. The philosophy is that
|
|
each URL should exist in one, and only one, place. Technically a URL
|
|
``foo.com/bar`` is distinct from ``foo.com/bar/`` -- a search-engine
|
|
indexer would treat them as separate URLs -- so it's best practice to
|
|
normalize URLs.
|
|
|
|
* Handles ETags based on the :setting:`USE_ETAGS` setting. If
|
|
:setting:`USE_ETAGS` is set to ``True``, Django will calculate an ETag
|
|
for each request by MD5-hashing the page content, and it'll take care of
|
|
sending ``Not Modified`` responses, if appropriate.
|
|
|
|
.. attribute:: CommonMiddleware.response_redirect_class
|
|
|
|
Defaults to :class:`~django.http.HttpResponsePermanentRedirect`. Subclass
|
|
``CommonMiddleware`` and override the attribute to customize the redirects
|
|
issued by the middleware.
|
|
|
|
.. class:: BrokenLinkEmailsMiddleware
|
|
|
|
* Sends broken link notification emails to :setting:`MANAGERS` (see
|
|
:doc:`/howto/error-reporting`).
|
|
|
|
Exception middleware
|
|
--------------------
|
|
|
|
.. module:: django.middleware.exception
|
|
:synopsis: Middleware to return responses for exceptions.
|
|
|
|
.. class:: ExceptionMiddleware
|
|
|
|
.. versionadded:: 1.10
|
|
|
|
Catches exceptions raised during the request/response cycle and returns the
|
|
appropriate response.
|
|
|
|
* :class:`~django.http.Http404` is processed by
|
|
:data:`~django.conf.urls.handler404` (or a more friendly debug page if
|
|
:setting:`DEBUG=True <DEBUG>`).
|
|
* :class:`~django.core.exceptions.PermissionDenied` is processed
|
|
by :data:`~django.conf.urls.handler403`.
|
|
* ``MultiPartParserError`` is processed by :data:`~django.conf.urls.handler400`.
|
|
* :class:`~django.core.exceptions.SuspiciousOperation` is processed by
|
|
:data:`~django.conf.urls.handler400` (or a more friendly debug page if
|
|
:setting:`DEBUG=True <DEBUG>`).
|
|
* Any other exception is processed by :data:`~django.conf.urls.handler500`
|
|
(or a more friendly debug page if :setting:`DEBUG=True <DEBUG>`).
|
|
|
|
Django uses this middleware regardless of whether or not you include it in
|
|
:setting:`MIDDLEWARE`, however, you may want to subclass if your own middleware
|
|
needs to transform any of these exceptions into the appropriate responses.
|
|
:class:`~django.middleware.locale.LocaleMiddleware` does this, for example.
|
|
|
|
GZip middleware
|
|
---------------
|
|
|
|
.. module:: django.middleware.gzip
|
|
:synopsis: Middleware to serve GZipped content for performance.
|
|
|
|
.. class:: GZipMiddleware
|
|
|
|
.. warning::
|
|
|
|
Security researchers recently revealed that when compression techniques
|
|
(including ``GZipMiddleware``) are used on a website, the site becomes
|
|
exposed to a number of possible attacks. These approaches can be used to
|
|
compromise, among other things, Django's CSRF protection. Before using
|
|
``GZipMiddleware`` on your site, you should consider very carefully whether
|
|
you are subject to these attacks. If you're in *any* doubt about whether
|
|
you're affected, you should avoid using ``GZipMiddleware``. For more
|
|
details, see the `the BREACH paper (PDF)`_ and `breachattack.com`_.
|
|
|
|
.. _the BREACH paper (PDF): http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf
|
|
.. _breachattack.com: http://breachattack.com
|
|
|
|
Compresses content for browsers that understand GZip compression (all modern
|
|
browsers).
|
|
|
|
This middleware should be placed before any other middleware that need to
|
|
read or write the response body so that compression happens afterward.
|
|
|
|
It will NOT compress content if any of the following are true:
|
|
|
|
* The content body is less than 200 bytes long.
|
|
|
|
* The response has already set the ``Content-Encoding`` header.
|
|
|
|
* The request (the browser) hasn't sent an ``Accept-Encoding`` header
|
|
containing ``gzip``.
|
|
|
|
You can apply GZip compression to individual views using the
|
|
:func:`~django.views.decorators.gzip.gzip_page()` decorator.
|
|
|
|
Conditional GET middleware
|
|
--------------------------
|
|
|
|
.. module:: django.middleware.http
|
|
:synopsis: Middleware handling advanced HTTP features.
|
|
|
|
.. class:: ConditionalGetMiddleware
|
|
|
|
Handles conditional GET operations. If the response has a ``ETag`` or
|
|
``Last-Modified`` header, and the request has ``If-None-Match`` or
|
|
``If-Modified-Since``, the response is replaced by an
|
|
:class:`~django.http.HttpResponseNotModified`.
|
|
|
|
Also sets the ``Date`` and ``Content-Length`` response-headers.
|
|
|
|
Locale middleware
|
|
-----------------
|
|
|
|
.. module:: django.middleware.locale
|
|
:synopsis: Middleware to enable language selection based on the request.
|
|
|
|
.. class:: LocaleMiddleware
|
|
|
|
Enables language selection based on data from the request. It customizes
|
|
content for each user. See the :doc:`internationalization documentation
|
|
</topics/i18n/translation>`.
|
|
|
|
.. attribute:: LocaleMiddleware.response_redirect_class
|
|
|
|
Defaults to :class:`~django.http.HttpResponseRedirect`. Subclass
|
|
``LocaleMiddleware`` and override the attribute to customize the redirects
|
|
issued by the middleware.
|
|
|
|
Message middleware
|
|
------------------
|
|
|
|
.. module:: django.contrib.messages.middleware
|
|
:synopsis: Message middleware.
|
|
|
|
.. class:: MessageMiddleware
|
|
|
|
Enables cookie- and session-based message support. See the
|
|
:doc:`messages documentation </ref/contrib/messages>`.
|
|
|
|
.. _security-middleware:
|
|
|
|
Security middleware
|
|
-------------------
|
|
|
|
.. module:: django.middleware.security
|
|
:synopsis: Security middleware.
|
|
|
|
.. warning::
|
|
If your deployment situation allows, it's usually a good idea to have your
|
|
front-end Web server perform the functionality provided by the
|
|
``SecurityMiddleware``. That way, if there are requests that aren't served
|
|
by Django (such as static media or user-uploaded files), they will have
|
|
the same protections as requests to your Django application.
|
|
|
|
.. class:: SecurityMiddleware
|
|
|
|
The ``django.middleware.security.SecurityMiddleware`` provides several security
|
|
enhancements to the request/response cycle. Each one can be independently
|
|
enabled or disabled with a setting.
|
|
|
|
* :setting:`SECURE_BROWSER_XSS_FILTER`
|
|
* :setting:`SECURE_CONTENT_TYPE_NOSNIFF`
|
|
* :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`
|
|
* :setting:`SECURE_HSTS_SECONDS`
|
|
* :setting:`SECURE_REDIRECT_EXEMPT`
|
|
* :setting:`SECURE_SSL_HOST`
|
|
* :setting:`SECURE_SSL_REDIRECT`
|
|
|
|
.. _http-strict-transport-security:
|
|
|
|
HTTP Strict Transport Security
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
For sites that should only be accessed over HTTPS, you can instruct modern
|
|
browsers to refuse to connect to your domain name via an insecure connection
|
|
(for a given period of time) by setting the `"Strict-Transport-Security"
|
|
header`_. This reduces your exposure to some SSL-stripping man-in-the-middle
|
|
(MITM) attacks.
|
|
|
|
``SecurityMiddleware`` will set this header for you on all HTTPS responses if
|
|
you set the :setting:`SECURE_HSTS_SECONDS` setting to a non-zero integer value.
|
|
|
|
When enabling HSTS, it's a good idea to first use a small value for testing,
|
|
for example, :setting:`SECURE_HSTS_SECONDS = 3600<SECURE_HSTS_SECONDS>` for one
|
|
hour. Each time a Web browser sees the HSTS header from your site, it will
|
|
refuse to communicate non-securely (using HTTP) with your domain for the given
|
|
period of time. Once you confirm that all assets are served securely on your
|
|
site (i.e. HSTS didn't break anything), it's a good idea to increase this value
|
|
so that infrequent visitors will be protected (31536000 seconds, i.e. 1 year,
|
|
is common).
|
|
|
|
Additionally, if you set the :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS` setting
|
|
to ``True``, ``SecurityMiddleware`` will add the ``includeSubDomains`` tag to
|
|
the ``Strict-Transport-Security`` header. This is recommended (assuming all
|
|
subdomains are served exclusively using HTTPS), otherwise your site may still
|
|
be vulnerable via an insecure connection to a subdomain.
|
|
|
|
.. warning::
|
|
The HSTS policy applies to your entire domain, not just the URL of the
|
|
response that you set the header on. Therefore, you should only use it if
|
|
your entire domain is served via HTTPS only.
|
|
|
|
Browsers properly respecting the HSTS header will refuse to allow users to
|
|
bypass warnings and connect to a site with an expired, self-signed, or
|
|
otherwise invalid SSL certificate. If you use HSTS, make sure your
|
|
certificates are in good shape and stay that way!
|
|
|
|
.. note::
|
|
If you are deployed behind a load-balancer or reverse-proxy server, and the
|
|
``Strict-Transport-Security`` header is not being added to your responses,
|
|
it may be because Django doesn't realize that it's on a secure connection;
|
|
you may need to set the :setting:`SECURE_PROXY_SSL_HEADER` setting.
|
|
|
|
.. _"Strict-Transport-Security" header: https://en.wikipedia.org/wiki/Strict_Transport_Security
|
|
|
|
.. _x-content-type-options:
|
|
|
|
``X-Content-Type-Options: nosniff``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Some browsers will try to guess the content types of the assets that they
|
|
fetch, overriding the ``Content-Type`` header. While this can help display
|
|
sites with improperly configured servers, it can also pose a security
|
|
risk.
|
|
|
|
If your site serves user-uploaded files, a malicious user could upload a
|
|
specially-crafted file that would be interpreted as HTML or JavaScript by
|
|
the browser when you expected it to be something harmless.
|
|
|
|
To learn more about this header and how the browser treats it, you can
|
|
read about it on the `IE Security Blog`_.
|
|
|
|
To prevent the browser from guessing the content type and force it to
|
|
always use the type provided in the ``Content-Type`` header, you can pass
|
|
the ``X-Content-Type-Options: nosniff`` header. ``SecurityMiddleware`` will
|
|
do this for all responses if the :setting:`SECURE_CONTENT_TYPE_NOSNIFF` setting
|
|
is ``True``.
|
|
|
|
Note that in most deployment situations where Django isn't involved in serving
|
|
user-uploaded files, this setting won't help you. For example, if your
|
|
:setting:`MEDIA_URL` is served directly by your front-end Web server (nginx,
|
|
Apache, etc.) then you'd want to set this header there. On the other hand, if
|
|
you are using Django to do something like require authorization in order to
|
|
download files and you cannot set the header using your Web server, this
|
|
setting will be useful.
|
|
|
|
.. _IE Security Blog: http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx
|
|
|
|
.. _x-xss-protection:
|
|
|
|
``X-XSS-Protection: 1; mode=block``
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Some browsers have the ability to block content that appears to be an `XSS
|
|
attack`_. They work by looking for JavaScript content in the GET or POST
|
|
parameters of a page. If the JavaScript is replayed in the server's response,
|
|
the page is blocked from rendering and an error page is shown instead.
|
|
|
|
The `X-XSS-Protection header`_ is used to control the operation of the
|
|
XSS filter.
|
|
|
|
To enable the XSS filter in the browser, and force it to always block
|
|
suspected XSS attacks, you can pass the ``X-XSS-Protection: 1; mode=block``
|
|
header. ``SecurityMiddleware`` will do this for all responses if the
|
|
:setting:`SECURE_BROWSER_XSS_FILTER` setting is ``True``.
|
|
|
|
.. warning::
|
|
The browser XSS filter is a useful defense measure, but must not be
|
|
relied upon exclusively. It cannot detect all XSS attacks and not all
|
|
browsers support the header. Ensure you are still :ref:`validating and
|
|
sanitizing <cross-site-scripting>` all input to prevent XSS attacks.
|
|
|
|
.. _XSS attack: https://en.wikipedia.org/wiki/Cross-site_scripting
|
|
.. _X-XSS-Protection header: http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx
|
|
|
|
.. _ssl-redirect:
|
|
|
|
SSL Redirect
|
|
~~~~~~~~~~~~
|
|
|
|
If your site offers both HTTP and HTTPS connections, most users will end up
|
|
with an unsecured connection by default. For best security, you should redirect
|
|
all HTTP connections to HTTPS.
|
|
|
|
If you set the :setting:`SECURE_SSL_REDIRECT` setting to True,
|
|
``SecurityMiddleware`` will permanently (HTTP 301) redirect all HTTP
|
|
connections to HTTPS.
|
|
|
|
.. note::
|
|
|
|
For performance reasons, it's preferable to do these redirects outside of
|
|
Django, in a front-end load balancer or reverse-proxy server such as
|
|
`nginx`_. :setting:`SECURE_SSL_REDIRECT` is intended for the deployment
|
|
situations where this isn't an option.
|
|
|
|
If the :setting:`SECURE_SSL_HOST` setting has a value, all redirects will be
|
|
sent to that host instead of the originally-requested host.
|
|
|
|
If there are a few pages on your site that should be available over HTTP, and
|
|
not redirected to HTTPS, you can list regular expressions to match those URLs
|
|
in the :setting:`SECURE_REDIRECT_EXEMPT` setting.
|
|
|
|
.. note::
|
|
If you are deployed behind a load-balancer or reverse-proxy server and
|
|
Django can't seem to tell when a request actually is already secure, you
|
|
may need to set the :setting:`SECURE_PROXY_SSL_HEADER` setting.
|
|
|
|
.. _nginx: http://nginx.org
|
|
|
|
Session middleware
|
|
------------------
|
|
|
|
.. module:: django.contrib.sessions.middleware
|
|
:synopsis: Session middleware.
|
|
|
|
.. class:: SessionMiddleware
|
|
|
|
Enables session support. See the :doc:`session documentation
|
|
</topics/http/sessions>`.
|
|
|
|
Site middleware
|
|
---------------
|
|
|
|
.. module:: django.contrib.sites.middleware
|
|
:synopsis: Site middleware.
|
|
|
|
.. class:: CurrentSiteMiddleware
|
|
|
|
Adds the ``site`` attribute representing the current site to every incoming
|
|
``HttpRequest`` object. See the :ref:`sites documentation <site-middleware>`.
|
|
|
|
Authentication middleware
|
|
-------------------------
|
|
|
|
.. module:: django.contrib.auth.middleware
|
|
:synopsis: Authentication middleware.
|
|
|
|
.. class:: AuthenticationMiddleware
|
|
|
|
Adds the ``user`` attribute, representing the currently-logged-in user, to
|
|
every incoming ``HttpRequest`` object. See :ref:`Authentication in Web requests
|
|
<auth-web-requests>`.
|
|
|
|
.. class:: RemoteUserMiddleware
|
|
|
|
Middleware for utilizing Web server provided authentication. See
|
|
:doc:`/howto/auth-remote-user` for usage details.
|
|
|
|
.. class:: PersistentRemoteUserMiddleware
|
|
|
|
.. versionadded:: 1.9
|
|
|
|
Middleware for utilizing Web server provided authentication when enabled only
|
|
on the login page. See :ref:`persistent-remote-user-middleware-howto` for usage
|
|
details.
|
|
|
|
CSRF protection middleware
|
|
--------------------------
|
|
|
|
.. module:: django.middleware.csrf
|
|
:synopsis: Middleware adding protection against Cross Site Request
|
|
Forgeries.
|
|
|
|
.. class:: CsrfViewMiddleware
|
|
|
|
Adds protection against Cross Site Request Forgeries by adding hidden form
|
|
fields to POST forms and checking requests for the correct value. See the
|
|
:doc:`Cross Site Request Forgery protection documentation </ref/csrf>`.
|
|
|
|
``X-Frame-Options`` middleware
|
|
------------------------------
|
|
|
|
.. module:: django.middleware.clickjacking
|
|
:synopsis: Clickjacking protection
|
|
|
|
.. class:: XFrameOptionsMiddleware
|
|
|
|
Simple :doc:`clickjacking protection via the X-Frame-Options header </ref/clickjacking/>`.
|
|
|
|
.. _middleware-ordering:
|
|
|
|
Middleware ordering
|
|
===================
|
|
|
|
Here are some hints about the ordering of various Django middleware classes:
|
|
|
|
#. :class:`~django.middleware.security.SecurityMiddleware`
|
|
|
|
It should go near the top of the list if you're going to turn on the SSL
|
|
redirect as that avoids running through a bunch of other unnecessary
|
|
middleware.
|
|
|
|
#. :class:`~django.middleware.cache.UpdateCacheMiddleware`
|
|
|
|
Before those that modify the ``Vary`` header (``SessionMiddleware``,
|
|
``GZipMiddleware``, ``LocaleMiddleware``).
|
|
|
|
#. :class:`~django.middleware.gzip.GZipMiddleware`
|
|
|
|
Before any middleware that may change or use the response body.
|
|
|
|
After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
|
|
|
|
#. :class:`~django.middleware.http.ConditionalGetMiddleware`
|
|
|
|
Before ``CommonMiddleware``: uses its ``Etag`` header when
|
|
:setting:`USE_ETAGS` = ``True``.
|
|
|
|
#. :class:`~django.contrib.sessions.middleware.SessionMiddleware`
|
|
|
|
After ``UpdateCacheMiddleware``: Modifies ``Vary`` header.
|
|
|
|
#. :class:`~django.middleware.locale.LocaleMiddleware`
|
|
|
|
One of the topmost, after ``SessionMiddleware`` (uses session data) and
|
|
``UpdateCacheMiddleware`` (modifies ``Vary`` header).
|
|
|
|
#. :class:`~django.middleware.common.CommonMiddleware`
|
|
|
|
Before any middleware that may change the response (it calculates ``ETags``).
|
|
|
|
After ``GZipMiddleware`` so it won't calculate an ``ETag`` header on gzipped
|
|
contents.
|
|
|
|
Close to the top: it redirects when :setting:`APPEND_SLASH` or
|
|
:setting:`PREPEND_WWW` are set to ``True``.
|
|
|
|
#. :class:`~django.middleware.csrf.CsrfViewMiddleware`
|
|
|
|
Before any view middleware that assumes that CSRF attacks have been dealt
|
|
with.
|
|
|
|
#. :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
|
|
|
|
After ``SessionMiddleware``: uses session storage.
|
|
|
|
#. :class:`~django.contrib.messages.middleware.MessageMiddleware`
|
|
|
|
After ``SessionMiddleware``: can use session-based storage.
|
|
|
|
#. :class:`~django.middleware.cache.FetchFromCacheMiddleware`
|
|
|
|
After any middleware that modifies the ``Vary`` header: that header is used
|
|
to pick a value for the cache hash-key.
|
|
|
|
#. :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`
|
|
|
|
Should be near the bottom as it's a last-resort type of middleware.
|
|
|
|
#. :class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware`
|
|
|
|
Should be near the bottom as it's a last-resort type of middleware.
|