中间件 — Django 文档
中间件
本文档解释了 Django 附带的所有中间件组件。 有关如何使用它们以及如何编写自己的中间件的信息,请参阅 中间件使用指南 。
可用的中间件
缓存中间件
- class UpdateCacheMiddleware
- class FetchFromCacheMiddleware
启用站点范围的缓存。 如果启用这些,每个 Django 驱动的页面将被缓存,只要 :setting:`CACHE_MIDDLEWARE_SECONDS` 设置定义。 请参阅 缓存文档 。
“通用”中间件
- class CommonMiddleware
为完美主义者增加了一些便利:
禁止访问 :setting:`DISALLOWED_USER_AGENTS` 设置中的用户代理,该设置应该是已编译的正则表达式对象列表。
根据 :setting:`APPEND_SLASH` 和 :setting:`PREPEND_WWW` 设置执行 URL 重写。
如果 :setting:`APPEND_SLASH` 是
True
并且初始 URL 不以斜杠结尾,并且在 URLconf 中找不到,则通过附加一个新 URL 形成斜线在最后。 如果在 URLconf 中找到了这个新 URL,那么 Django 会将请求重定向到这个新 URL。 否则,将照常处理初始 URL。例如,如果
foo.com/bar
没有有效的 URL 模式,但 do 有 的有效模式,则foo.com/bar
将被重定向到foo.com/bar/
X148X]。如果 :setting:`PREPEND_WWW` 是
True
,则缺少前导“www”的 URL。 将被重定向到以“www”开头的相同 URL。这两个选项都用于规范化 URL。 其理念是每个 URL 都应存在于一个且仅一个位置。 从技术上讲,URL
foo.com/bar
与foo.com/bar/
不同——搜索引擎索引器会将它们视为单独的 URL——因此最佳做法是规范化 URL。为非流响应设置
Content-Length
标头。
- CommonMiddleware.response_redirect_class
默认为 HttpResponsePermanentRedirect。 子类 CommonMiddleware
并覆盖该属性以自定义中间件发出的重定向。
- class BrokenLinkEmailsMiddleware
- 向 :setting:`MANAGERS` 发送断开链接通知电子邮件(请参阅 错误报告 )。
GZip 中间件
- class GZipMiddleware
警告
安全研究人员最近透露,当在网站上使用压缩技术(包括 GZipMiddleware
)时,该网站可能会受到多种可能的攻击。 在您的站点上使用 GZipMiddleware
之前,您应该非常仔细地考虑您是否受到这些攻击。 如果你在 任何 怀疑你是否受到影响,你应该避免使用 GZipMiddleware
。 有关更多详细信息,请参阅 the BREACH 论文 (PDF) 和 breachattack.com。
django.middleware.gzip.GZipMiddleware
为理解 GZip 压缩的浏览器(所有现代浏览器)压缩内容。
这个中间件应该放在任何其他需要读取或写入响应体的中间件之前,这样压缩就会在之后发生。
如果以下任何一项为真,它将不会压缩内容:
- 内容主体长度小于 200 字节。
- 响应已经设置了
Content-Encoding
标头。 - 请求(浏览器)尚未发送包含
gzip
的Accept-Encoding
标头。
如果响应具有 ETag
标头,则 ETag 会变弱以符合 RFC 7232#section-2.1。
您可以使用 gzip_page() 装饰器将 GZip 压缩应用于单个视图。
条件 GET 中间件
- class ConditionalGetMiddleware
处理条件 GET 操作。 如果响应没有 ETag
标头,中间件会根据需要添加一个。 如果响应具有 ETag
或 Last-Modified
标头,并且请求具有 If-None-Match
或 If-Modified-Since
,则响应被替换为 HttpResponseNotModified ]。
本地化中间件
- class LocaleMiddleware
根据请求中的数据启用语言选择。 它为每个用户定制内容。 请参阅 国际化文档 。
- LocaleMiddleware.response_redirect_class
默认为 HttpResponseRedirect。 子类 LocaleMiddleware
并覆盖该属性以自定义中间件发出的重定向。
安全中间件
警告
如果您的部署情况允许,让您的前端 Web 服务器执行 SecurityMiddleware
提供的功能通常是个好主意。 这样,如果有 Django 不提供的请求(例如静态媒体或用户上传的文件),它们将具有与对 Django 应用程序的请求相同的保护。
- class SecurityMiddleware
django.middleware.security.SecurityMiddleware
为请求/响应周期提供了多项安全增强功能。 每个都可以通过设置独立启用或禁用。
- :setting:`SECURE_BROWSER_XSS_FILTER`
- :setting:`SECURE_CONTENT_TYPE_NOSNIFF`
- :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS`
- :setting:`SECURE_HSTS_PRELOAD`
- :setting:`SECURE_HSTS_SECONDS`
- :setting:`SECURE_REDIRECT_EXEMPT`
- :setting:`SECURE_SSL_HOST`
- :setting:`SECURE_SSL_REDIRECT`
HTTP 严格传输安全
对于只能通过 HTTPS 访问的站点,您可以通过设置 “Strict-Transport-Security” 标头 “Strict-Transport-Security” 标头,指示现代浏览器拒绝通过不安全连接(在给定时间段内)连接到您的域名X234X]。 这减少了您遭受某些 SSL 剥离中间人 (MITM) 攻击的风险。
如果您将 :setting:`SECURE_HSTS_SECONDS` 设置为非零整数值,SecurityMiddleware
将在所有 HTTPS 响应中为您设置此标头。
启用 HSTS 时,最好先使用较小的值进行测试,例如, :设置:`SECURE_HSTS_SECONDS = 3600 ` 一小时。 每次 Web 浏览器从您的站点看到 HSTS 标头时,它都会在给定的时间段内拒绝与您的域进行非安全(使用 HTTP)通信。 一旦您确认所有资产都在您的网站上安全地提供(即 HSTS 没有破坏任何东西),增加这个值是个好主意,这样不频繁的访问者将受到保护(31536000 秒,即 1 年,很常见)。
此外,如果您将 :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS` 设置为 True
,SecurityMiddleware
会将 includeSubDomains
指令添加到 [X15] ] 标题。 这是推荐的(假设所有子域都只使用 HTTPS 提供服务),否则您的站点可能仍然容易通过与子域的不安全连接而受到攻击。
如果您希望将您的站点提交到 浏览器预加载列表 ,请将 :setting:`SECURE_HSTS_PRELOAD` 设置为 True
。 将 preload
指令附加到 Strict-Transport-Security
标头。
警告
HSTS 策略适用于您的整个域,而不仅仅是您设置标头的响应的 URL。 因此,仅当您的整个域仅通过 HTTPS 提供服务时才应使用它。
正确遵守 HSTS 标头的浏览器将拒绝允许用户绕过警告并连接到具有过期、自签名或其他无效 SSL 证书的站点。 如果您使用 HSTS,请确保您的证书状态良好并保持这种状态!
笔记
如果您部署在负载平衡器或反向代理服务器之后,并且 Strict-Transport-Security
标头未添加到您的响应中,则可能是因为 Django 没有意识到它处于安全连接上; 您可能需要设置 :setting:`SECURE_PROXY_SSL_HEADER` 设置。
X-Content-Type-Options: nosniff
一些浏览器会尝试猜测它们获取的资产的内容类型,覆盖 Content-Type
标头。 虽然这有助于显示服务器配置不当的站点,但它也可能带来安全风险。
如果你的网站提供用户上传的文件,恶意用户可能会上传一个特制的文件,当你认为它是无害的东西时,该文件会被浏览器解释为 HTML 或 JavaScript。
为了防止浏览器猜测内容类型并强制它始终使用 Content-Type
标头中提供的类型,您可以传递 X-Content-Type-Options: nosniff 标头。 SecurityMiddleware
将对所有响应执行此操作,如果 :setting:`SECURE_CONTENT_TYPE_NOSNIFF` 设置为 True
。
请注意,在 Django 不参与为用户上传的文件提供服务的大多数部署情况下,此设置对您没有帮助。 例如,如果您的 :setting:`MEDIA_URL` 直接由您的前端 Web 服务器(nginx、Apache 等)提供服务,那么您需要在那里设置此标头。 另一方面,如果您使用 Django 执行诸如需要授权才能下载文件之类的操作,并且您无法使用 Web 服务器设置标头,则此设置将很有用。
X-XSS-Protection: 1; mode=block
某些浏览器能够阻止看起来像是 XSS 攻击 的内容。 它们通过在页面的 GET 或 POST 参数中查找 JavaScript 内容来工作。 如果 JavaScript 在服务器的响应中被重播,页面将被阻止呈现并显示错误页面。
X-XSS-Protection头用于控制XSS过滤器的操作。
要在浏览器中启用 XSS 过滤器,并强制它始终阻止可疑的 XSS 攻击,您可以传递 X-XSS-Protection: 1; mode=block
标头。 如果 :setting:`SECURE_BROWSER_XSS_FILTER` 设置为 True
,SecurityMiddleware
将对所有响应执行此操作。
SSL 重定向
如果您的站点同时提供 HTTP 和 HTTPS 连接,默认情况下大多数用户最终会使用不安全的连接。 为了获得最佳安全性,您应该将所有 HTTP 连接重定向到 HTTPS。
如果您将 :setting:`SECURE_SSL_REDIRECT` 设置为 True,SecurityMiddleware
将永久 (HTTP 301) 将所有 HTTP 连接重定向到 HTTPS。
笔记
出于性能原因,最好在 Django 之外、在前端负载平衡器或反向代理服务器(如 nginx)中进行这些重定向。 :setting:`SECURE_SSL_REDIRECT` 适用于无法选择的部署情况。
如果 :setting:`SECURE_SSL_HOST` 设置具有值,则所有重定向都将发送到该主机而不是最初请求的主机。
如果您的站点上有几个页面应该可以通过 HTTP 访问,而不是重定向到 HTTPS,您可以在 :setting:`SECURE_REDIRECT_EXEMPT` 设置中列出与这些 URL 匹配的正则表达式。
验证中间件
- class AuthenticationMiddleware
向每个传入的 HttpRequest
对象添加表示当前登录用户的 user
属性。 请参阅 Web 请求中的身份验证 。
- class RemoteUserMiddleware
用于利用 Web 服务器提供的身份验证的中间件。 有关使用详细信息,请参阅 使用 REMOTE_USER 进行身份验证。
- class PersistentRemoteUserMiddleware
仅在登录页面上启用时,用于利用 Web 服务器提供的身份验证的中间件。 有关使用详细信息,请参阅 仅在登录页面上使用 REMOTE_USER 。
中间件顺序
下面是关于各种 Django 中间件类的排序的一些提示:
-
如果您要打开 SSL 重定向,它应该靠近列表的顶部,因为这样可以避免运行一堆其他不必要的中间件。
-
在修改
Vary
头文件之前(SessionMiddleware
、GZipMiddleware
、LocaleMiddleware
)。 -
在任何可能改变或使用响应体的中间件之前。
UpdateCacheMiddleware
后:修改Vary
标题。 -
如果您使用 :setting:`CSRF_USE_SESSIONS`,则在任何可能引发异常以触发错误视图(例如 PermissionDenied)的中间件之前。
UpdateCacheMiddleware
后:修改Vary
标题。 -
在任何可能更改响应的中间件之前(它设置
ETag
标头)。在
GZipMiddleware
之后,它不会计算 gzipped 内容的ETag
标头。 -
最顶层之一,在
SessionMiddleware
(使用会话数据)和UpdateCacheMiddleware
(修改Vary
标头)之后。 -
在任何可能更改响应的中间件之前(它设置
Content-Length
标头)。 出现在CommonMiddleware
之前并更改响应的中间件必须重置Content-Length
。靠近顶部:当 :setting:`APPEND_SLASH` 或 :setting:`PREPEND_WWW` 设置为
True
时重定向。在
SessionMiddleware
之后,如果您使用 :setting:`CSRF_USE_SESSIONS`。 -
在任何假设 CSRF 攻击已经被处理的视图中间件之前。
在 RemoteUserMiddleware 或任何其他可能执行登录并因此轮换 CSRF 令牌的身份验证中间件之前,在调用中间件链之前。
在
SessionMiddleware
之后,如果您使用 :setting:`CSRF_USE_SESSIONS`。 -
SessionMiddleware
之后:使用会话存储。 -
SessionMiddleware
之后:可以使用基于会话的存储。 -
在修改
Vary
标头的任何中间件之后:该标头用于为缓存哈希键选择一个值。 -
应该靠近底部,因为它是最后的中间件类型。
-
应该靠近底部,因为它是最后的中间件类型。