中间件 — 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。如有必要,可以使用 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
- 向 :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 压缩应用于单个视图。
条件获取中间件
- 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
为请求/响应周期提供了多项安全增强功能。 每个都可以通过设置独立启用或禁用。
- :设置:`SECURE_BROWSER_XSS_FILTER`
- :设置:`SECURE_CONTENT_TYPE_NOSNIFF`
- :设置:`SECURE_HSTS_INCLUDE_SUBDOMAINS`
- :设置:`SECURE_HSTS_PRELOAD`
- :设置:`SECURE_HSTS_SECONDS`
- :设置:`SECURE_REDIRECT_EXEMPT`
- :设置:`SECURE_REFERRER_POLICY`
- :设置:`SECURE_SSL_HOST`
- :设置:`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` 设置。
推荐人政策
浏览器使用 引用标头 作为向站点发送有关用户如何到达那里的信息的一种方式。 当用户单击链接时,浏览器将发送链接页面的完整 URL 作为引用者。 虽然这对某些目的很有用——比如找出谁链接到你的网站——但它也可能会通过通知一个网站用户正在访问另一个网站而引起隐私问题。
某些浏览器能够接受有关在用户单击链接时是否应该发送 HTTP Referer
标头的提示; 此提示是通过 引用策略标头 提供的。 此标头可以向浏览器建议以下三种行为中的任何一种:
- 完整 URL:在
Referer
标头中发送整个 URL。 例如,如果用户正在访问https://example.com/page.html
,则Referer
标头将包含"https://example.com/page.html%22
。 - 仅来源:仅发送推荐人中的“来源”。 来源由方案、主机和(可选)端口号组成。 例如,如果用户正在访问
https://example.com/page.html
,则原点将是https://example.com/
。 - 无引用:根本不发送
Referer
标头。
此标头可以告诉浏览器注意两种类型的条件:
- 同源与跨源:从
https://example.com/1.html
到https://example.com/2.html
的链接是同源的。 从https://example.com/page.html
到https://not.example.com/page.html
的链接是跨域的。 - 协议降级:如果包含链接的页面通过 HTTPS 提供服务,但链接到的页面不是通过 HTTPS 提供服务,则会发生降级。
警告
当您的站点通过 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` 设置为 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
标头的任何中间件之后:该标头用于为缓存哈希键选择一个值。 -
应该靠近底部,因为它是最后的中间件类型。
-
应该靠近底部,因为它是最后的中间件类型。