中间件 — Django 文档

来自菜鸟教程
Django/docs/3.2.x/ref/middleware
跳转至:导航、​搜索

中间件

本文档解释了 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/barfoo.com/bar/ 不同——搜索引擎索引器会将它们视为单独的 URL——因此最佳做法是规范化 URL。

    如有必要,可以使用 no_append_slash() 装饰器将单个视图从 APPEND_SLASH 行为中排除:

    from django.views.decorators.common import no_append_slash
    
    @no_append_slash
    def sensitive_fbv(request, *args, **kwargs):
        """View to be excluded from APPEND_SLASH."""
        return HttpResponse()

    3.2 版更改: 添加了对 no_append_slash() 装饰器的支持。

  • 为非流响应设置 Content-Length 标头。

CommonMiddleware.response_redirect_class

默认为 HttpResponsePermanentRedirect。 子类 CommonMiddleware 并覆盖该属性以自定义中间件发出的重定向。

class BrokenLinkEmailsMiddleware


GZip中间件

class GZipMiddleware

警告

安全研究人员最近透露,当在网站上使用压缩技术(包括 GZipMiddleware)时,该网站可能会受到多种可能的攻击。 在您的站点上使用 GZipMiddleware 之前,您应该非常仔细地考虑您是否受到这些攻击。 如果你在 任何 怀疑你是否受到影响,你应该避免使用 GZipMiddleware。 有关更多详细信息,请参阅 the BREACH 论文 (PDF)breachattack.com


django.middleware.gzip.GZipMiddleware 为理解 GZip 压缩的浏览器(所有现代浏览器)压缩内容。

该中间件应放置在需要读取或写入响应正文的任何其他中间件之前,以便随后进行压缩。

如果以下任何一项为真,它将不会压缩内容:

  • 内容主体长度小于 200 字节。
  • 响应已经设置了 Content-Encoding 标头。
  • 请求(浏览器)尚未发送包含 gzipAccept-Encoding 标头。

如果响应具有 ETag 标头,则 ETag 会变弱以符合 RFC 7232#section-2.1

您可以使用 gzip_page() 装饰器将 GZip 压缩应用于单个视图。


条件获取中间件

class ConditionalGetMiddleware

处理条件 GET 操作。 如果响应没有 ETag 标头,中间件会根据需要添加一个。 如果响应具有 ETagLast-Modified 标头,并且请求具有 If-None-MatchIf-Modified-Since,则响应被替换为 HttpResponseNotModified ]。


语言环境中间件

class LocaleMiddleware

根据请求中的数据启用语言选择。 它为每个用户定制内容。 请参阅 国际化文档

LocaleMiddleware.response_redirect_class

默认为 HttpResponseRedirect。 子类 LocaleMiddleware 并覆盖该属性以自定义中间件发出的重定向。


消息中间件

class MessageMiddleware

启用基于 cookie 和会话的消息支持。 请参阅 消息文档


安全中间件

警告

如果您的部署情况允许,让您的前端 Web 服务器执行 SecurityMiddleware 提供的功能通常是个好主意。 这样,如果有 Django 不提供的请求(例如静态媒体或用户上传的文件),它们将具有与对 Django 应用程序的请求相同的保护。


class SecurityMiddleware

django.middleware.security.SecurityMiddleware 为请求/响应周期提供了多项安全增强功能。 每个都可以通过设置独立启用或禁用。

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` 设置为 TrueSecurityMiddleware 会将 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` 设置。


推荐人政策

浏览器使用 引用标头 作为向站点发送有关用户如何到达那里的信息的一种方式。 当用户单击链接时,浏览器将发送链接页面的完整 URL 作为引用者。 虽然这对某些目的很有用——比如找出谁链接到你的网站——但它也可能会通过通知一个网站用户正在访问另一个网站而引起隐私问题。

某些浏览器能够接受有关在用户单击链接时是否应该发送 HTTP Referer 标头的提示; 此提示是通过 引用策略标头 提供的。 此标头可以向浏览器建议以下三种行为中的任何一种:

此标头可以告诉浏览器注意两种类型的条件:

警告

当您的站点通过 HTTPS 提供服务时,Django 的 CSRF 保护系统 要求存在 Referer 标头,因此完全禁用 Referer 标头会干扰 CSRF 保护。 要获得禁用 Referer 标头的大部分好处,同时保持 CSRF 保护,请考虑仅启用同源引用。


SecurityMiddleware 可以根据 :setting:`SECURE_REFERRER_POLICY` 设置为您设置 Referrer-Policy 标头(注意拼写:浏览器发送 Referer 标头时用户单击一个链接,但指示浏览器是否这样做的标题拼写为 Referrer-Policy)。 此设置的有效值为:

no-referrer
指示浏览器不为在此站点上单击的链接发送引荐来源网址。
no-referrer-when-downgrade
指示浏览器发送完整的 URL 作为引用者,但仅当没有发生协议降级时。
origin
指示浏览器仅发送来源,而不是完整的 URL,作为引用者。
origin-when-cross-origin
指示浏览器发送完整的 URL 作为同源链接的引用来源,并且只发送跨源链接的来源。
same-origin
指示浏览器发送完整的 URL,但仅用于同源链接。 不会为跨源链接发送推荐人。
strict-origin
指示浏览器仅发送源,而不是完整的 URL,并且在发生协议降级时不发送引用。
strict-origin-when-cross-origin
当链接是同源的并且没有发生协议降级时,指示浏览器发送完整的URL; 当链路是跨域的并且没有发生协议降级时,只发送源; 并且在发生协议降级时没有引用者。
unsafe-url
指示浏览器始终将完整 URL 作为引用者发送。

未知的策略值

如果用户代理的策略值为 unknown,则可以指定多个策略值以提供回退。 最后一个被理解的指定值优先。 为了支持这一点,可以将可迭代或逗号分隔的字符串与 :setting:`SECURE_REFERRER_POLICY` 一起使用。


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` 设置为 TrueSecurityMiddleware 将对所有响应执行此操作。

警告

浏览器 XSS 过滤器是一种有用的防御措施,但不能完全依赖。 它不能检测所有 XSS 攻击,也不是所有浏览器都支持标头。 确保您仍在 验证和清理 所有输入以防止 XSS 攻击。


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 匹配的正则表达式。

笔记

如果您部署在负载均衡器或反向代理服务器之后并且 Django 似乎无法判断请求何时实际上已经安全,则您可能需要设置 :setting:`SECURE_PROXY_SSL_HEADER` 设置。


会话中间件

class SessionMiddleware

启用会话支持。 请参阅 会话文档


站点中间件

class CurrentSiteMiddleware

将表示当前站点的 site 属性添加到每个传入的 HttpRequest 对象。 请参阅 站点文档


认证中间件

class AuthenticationMiddleware

向每个传入的 HttpRequest 对象添加表示当前登录用户的 user 属性。 请参阅 Web 请求中的身份验证

class RemoteUserMiddleware

用于利用 Web 服务器提供的身份验证的中间件。 有关使用详细信息,请参阅 使用 REMOTE_USER 进行身份验证。

class PersistentRemoteUserMiddleware

仅在登录页面上启用时,用于利用 Web 服务器提供的身份验证的中间件。 有关使用详细信息,请参阅 仅在登录页面上使用 REMOTE_USER


CSRF 保护中间件

class CsrfViewMiddleware

通过向 POST 表单添加隐藏表单字段并检查请求的正确值来增加对跨站点请求伪造的保护。 请参阅 跨站点请求伪造保护文档


X-Frame-Options 中间件

class XFrameOptionsMiddleware

通过 X-Frame-Options 标头 进行简单的 点击劫持保护。


中间件订购

以下是有关各种 Django 中间件类的排序的一些提示:

  1. SecurityMiddleware

    如果您要打开 SSL 重定向,它应该靠近列表的顶部,因为这样可以避免运行一堆其他不必要的中间件。

  2. UpdateCacheMiddleware

    在修改 Vary 头文件之前(SessionMiddlewareGZipMiddlewareLocaleMiddleware)。

  3. GZipMiddleware

    在任何可能更改或使用响应正文的中间件之前。

    UpdateCacheMiddleware 后:修改 Vary 标题。

  4. SessionMiddleware

    如果您使用 :setting:`CSRF_USE_SESSIONS`,则在任何可能引发异常以触发错误视图(例如 PermissionDenied)的中间件之前。

    UpdateCacheMiddleware 后:修改 Vary 标题。

  5. ConditionalGetMiddleware

    在任何可能更改响应的中间件之前(它设置 ETag 标头)。

    GZipMiddleware 之后,它不会计算 gzipped 内容的 ETag 标头。

  6. LocaleMiddleware

    最顶层之一,在 SessionMiddleware(使用会话数据)和 UpdateCacheMiddleware(修改 Vary 标头)之后。

  7. CommonMiddleware

    在任何可能更改响应的中间件之前(它设置 Content-Length 标头)。 出现在 CommonMiddleware 之前并更改响应的中间件必须重置 Content-Length

    靠近顶部:当 :setting:`APPEND_SLASH`:setting:`PREPEND_WWW` 设置为 True 时重定向。

    SessionMiddleware 之后,如果您使用 :setting:`CSRF_USE_SESSIONS`

  8. CsrfViewMiddleware

    在任何假设 CSRF 攻击已被处理的视图中间件之前。

    RemoteUserMiddleware 或任何其他可能执行登录并因此轮换 CSRF 令牌的身份验证中间件之前,在调用中间件链之前。

    SessionMiddleware 之后,如果您使用 :setting:`CSRF_USE_SESSIONS`

  9. AuthenticationMiddleware

    SessionMiddleware 之后:使用会话存储。

  10. MessageMiddleware

    SessionMiddleware之后:可以使用基于会话的存储。

  11. FetchFromCacheMiddleware

    在修改 Vary 标头的任何中间件之后:该标头用于为缓存哈希键选择一个值。

  12. FlatpageFallbackMiddleware

    应该靠近底部,因为它是最后的中间件类型。

  13. RedirectFallbackMiddleware

    应该靠近底部,因为它是最后的中间件类型。