中间件¶
本文档解释了 Django 附带的所有中间件组件。有关如何使用它们以及如何编写自己的中间件的信息,请参阅中间件使用指南。
可用中间件¶
缓存中间件¶
-
class
UpdateCacheMiddleware
¶
-
class
FetchFromCacheMiddleware
¶
启用站点范围缓存。如果启用这些缓存,每个由 Django 提供支持的页面都将被缓存,只要CACHE_MIDDLEWARE_SECONDS
设置定义的时间。请参阅缓存文档。
“通用”中间件¶
-
class
CommonMiddleware
¶
为完美主义者增加了一些便利功能
禁止访问
DISALLOWED_USER_AGENTS
设置中的用户代理,该设置应为已编译的正则表达式对象列表。根据
APPEND_SLASH
和PREPEND_WWW
设置执行 URL 重写。如果
APPEND_SLASH
为True
且初始 URL 未以斜杠结尾,且在 URLconf 中未找到,则会通过在末尾追加斜杠来形成一个新的 URL。如果在 URLconf 中找到了此新 URL,则 Django 会将请求重定向到此新 URL。否则,将按常规处理初始 URL。例如,如果没有
foo.com/bar
的有效 URL 模式,但有foo.com/bar/
的有效模式,则foo.com/bar
将被重定向到foo.com/bar/
。如果
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()
为非流式响应设置
Content-Length
标头。
-
CommonMiddleware.
response_redirect_class
¶
默认为 HttpResponsePermanentRedirect
。子类化 CommonMiddleware
并覆盖该属性以自定义中间件发出的重定向。
-
类
BrokenLinkEmailsMiddleware
¶
GZip 中间件¶
注意
安全研究人员发现,当在网站上使用压缩技术(包括 GZipMiddleware
)时,该网站可能会受到多种可能的攻击。
为了减轻攻击,Django 实施了一种称为Heal The Breach (HTB) 的技术。它向每个响应添加多达 100 个字节(请参阅 max_random_bytes
)的随机字节,以降低攻击的有效性。
有关更多详细信息,请参阅 BREACH 论文 (PDF)、breachattack.com 和 Heal The Breach (HTB) 论文。
添加了对 BREACH 攻击的缓解措施。
django.middleware.gzip.GZipMiddleware
为理解 GZip 压缩(所有现代浏览器)的浏览器压缩内容。
此中间件应置于需要读取或写入响应正文的任何其他中间件之前,以便之后进行压缩。
如果满足以下任何条件,它将不会压缩内容
- 内容正文长度小于 200 个字节。
- 响应已设置
Content-Encoding
标头。 - 请求(浏览器)未发送包含
gzip
的Accept-Encoding
标头。
如果响应具有 ETag
头部,则会将 ETag 设为弱以符合 RFC 9110#section-8.8.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 应用程序的请求具有相同的保护措施。
-
类
SecurityMiddleware
¶
django.middleware.security.SecurityMiddleware
为请求/响应周期提供多项安全增强功能。每个功能都可以通过设置独立启用或禁用。
SECURE_CONTENT_TYPE_NOSNIFF
SECURE_CROSS_ORIGIN_OPENER_POLICY
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” 标头 来指示现代浏览器拒绝通过不安全的连接(在给定时间段内)连接到您的域名。这会降低您面临某些 SSL 剥离中间人 (MITM) 攻击的风险。
SecurityMiddleware
如果将 SECURE_HSTS_SECONDS
设置为非零整数,它将为所有 HTTPS 响应设置此标头。
启用 HSTS 时,最好先使用较小的值进行测试,例如,SECURE_HSTS_SECONDS = 3600
表示一小时。每次 Web 浏览器从您的网站看到 HSTS 标头时,它都会拒绝使用非安全方式(使用 HTTP)与您的域名进行通信,持续给定的时间段。一旦您确认网站上的所有资产都以安全方式提供(即 HSTS 没有破坏任何内容),最好增加此值,以便保护不常访问的访问者(31536000 秒,即 1 年,很常见)。
此外,如果您将 SECURE_HSTS_INCLUDE_SUBDOMAINS
设置为 True
,SecurityMiddleware
将 includeSubDomains
指令添加到 Strict-Transport-Security
标头。建议这样做(假设所有子域名都仅使用 HTTPS 提供),否则您的网站仍可能通过与子域名的不安全连接而受到攻击。
如果您希望将您的网站提交到 浏览器预加载列表,请将 SECURE_HSTS_PRELOAD
设置为 True
。这会将 preload
指令附加到 Strict-Transport-Security
标头。
警告
HSTS 策略适用于您的整个域名,而不仅仅是您设置标头的响应的 URL。因此,只有当您的整个域名仅通过 HTTPS 提供时,您才应该使用它。
正确遵守 HSTS 标头的浏览器将拒绝允许用户绕过警告并连接到具有已过期、自签名或其他无效 SSL 证书的网站。如果您使用 HSTS,请确保您的证书状态良好并保持这种状态!
注意
如果您部署在负载均衡器或反向代理服务器后面,并且 Strict-Transport-Security
标头未添加到您的响应中,这可能是因为 Django 无法识别它处于安全连接中;您可能需要设置 SECURE_PROXY_SSL_HEADER
设置。
引用者策略¶
浏览器使用 引用者标头 作为向网站发送有关用户如何到达该网站的信息的一种方式。当用户单击链接时,浏览器会将链接页面的完整 URL 作为引用者发送。虽然这对于某些目的(例如弄清楚谁链接到您的网站)很有用,但它也可能通过通知一个网站用户正在访问另一个网站而引起隐私问题。
一些浏览器能够接受有关当用户单击链接时是否应该发送 HTTP Referer
标头的提示;此提示通过 引用者策略标头 提供。此标头可以向浏览器建议三种行为
- 完整 URL:在
Referer
标头中发送整个 URL。例如,如果用户访问https://example.com/page.html
,则Referer
标头将包含"https://example.com/page.html"
。 - 仅来源:仅在引用者中发送“来源”。来源由方案、主机和(可选)端口号组成。例如,如果用户访问
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
可以根据 SECURE_REFERRER_POLICY
设置(注意拼写:当用户单击链接时,浏览器会发送 Referer
头部,但指示浏览器是否这样做的头部拼写为 Referrer-Policy
)为您设置 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 作为引荐者发送。
未知策略值
如果用户代理不知道策略值,未知,则可以指定多个策略值来提供后备。最后指定的已理解值优先。为了支持这一点,可以使用可迭代或逗号分隔的字符串与 SECURE_REFERRER_POLICY
。
跨源开启者策略¶
一些浏览器能够根据 跨源开启者策略 (COOP) 标头值将顶级窗口与其他文档隔离,方法是将它们放入单独的浏览上下文组中。如果以这种方式隔离的文档打开跨源弹出窗口,则弹出窗口的 window.opener
属性将为 null
。使用 COOP 隔离窗口是针对跨源攻击的纵深防御保护,特别是那些允许从加载到共享浏览上下文中提取数据(如 Spectre)的攻击。
SecurityMiddleware
可以根据 SECURE_CROSS_ORIGIN_OPENER_POLICY
设置,为您设置 Cross-Origin-Opener-Policy
标头。此设置的有效值为
same-origin
- 将浏览上下文专门隔离到同源文档。跨源文档不会加载到同一浏览上下文中。这是默认且最安全的选择。
same-origin-allow-popups
- 将浏览上下文隔离到同源文档或那些未设置 COOP 或通过设置 COOP 为
unsafe-none
来选择退出隔离的文档。 unsafe-none
- 允许将文档添加到其开启者的浏览上下文组,除非开启者本身的 COOP 为
same-origin
或same-origin-allow-popups
。
X-Content-Type-Options: nosniff
¶
一些浏览器会尝试猜测它们获取的资产的内容类型,覆盖 Content-Type
标头。虽然这有助于显示服务器配置不当的网站,但它也可能构成安全风险。
如果您的网站提供用户上传的文件,恶意用户可以上传一个经过特殊设计的,当您期望它成为无害内容时,会被浏览器解释为 HTML 或 JavaScript 的文件。
要防止浏览器猜测内容类型并强制其始终使用 Content-Type
标头中提供的类型,您可以传递 X-Content-Type-Options: nosniff 标头。如果 SECURE_CONTENT_TYPE_NOSNIFF
设置为 True
,SecurityMiddleware
将对所有响应执行此操作。
请注意,在大多数 Django 不参与提供用户上传文件的情况中,此设置对您没有帮助。例如,如果您的 MEDIA_URL
由您的前端 Web 服务器(nginx、Apache 等)直接提供,那么您需要在那里设置此标头。另一方面,如果您使用 Django 执行诸如要求授权才能下载文件之类的操作,并且您无法使用 Web 服务器设置标头,此设置将非常有用。
SSL 重定向¶
如果您的网站同时提供 HTTP 和 HTTPS 连接,大多数用户最终默认使用不安全的连接。为了获得最佳安全性,您应该将所有 HTTP 连接重定向到 HTTPS。
如果您将 SECURE_SSL_REDIRECT
设置为 True,SecurityMiddleware
将永久(HTTP 301)将所有 HTTP 连接重定向到 HTTPS。
注意
出于性能原因,最好在 Django 外部,在前端负载均衡器或反向代理服务器(如 nginx)中执行这些重定向。 SECURE_SSL_REDIRECT
适用于无法选择此选项的情况。
如果 SECURE_SSL_HOST
设置有值,所有重定向都将发送到该主机,而不是最初请求的主机。
如果您的网站上有一些页面应该通过 HTTP 提供,而不是重定向到 HTTPS,您可以在 SECURE_REDIRECT_EXEMPT
设置中列出正则表达式以匹配这些 URL。
注意
如果您部署在负载均衡器或反向代理服务器后面,并且 Django 似乎无法判断请求实际上是否已经安全,您可能需要设置 SECURE_PROXY_SSL_HEADER
设置。
身份验证中间件¶
-
class
AuthenticationMiddleware
¶
向每个传入 HttpRequest
对象添加表示当前登录用户的 user
属性。请参阅 Web 请求中的身份验证。
-
class
RemoteUserMiddleware
¶
用于利用 Web 服务器提供的身份验证的中间件。有关使用详细信息,请参阅 如何使用 REMOTE_USER 进行身份验证。
-
class
PersistentRemoteUserMiddleware
¶
仅在登录页面启用时用于利用 Web 服务器提供的身份验证的中间件。有关使用详细信息,请参阅 仅在登录页面上使用 REMOTE_USER。
中间件排序¶
以下是有关各种 Django 中间件类排序的一些提示
-
如果您要启用 SSL 重定向,则它应该位于列表的顶部,因为这样可以避免运行大量其他不必要的中间件。
-
在修改
Vary
头 (SessionMiddleware
、GZipMiddleware
、LocaleMiddleware
) 的中间件之前。 -
在任何可能更改或使用响应正文的中间件之前。
在
UpdateCacheMiddleware
之后:修改Vary
头。 -
在任何可能引发异常以触发错误视图(例如
PermissionDenied
)的中间件之前,如果您正在使用CSRF_USE_SESSIONS
。在
UpdateCacheMiddleware
之后:修改Vary
头。 -
在任何可能更改响应的中间件之前(它设置
ETag
标头)。在
GZipMiddleware
之后,因此它不会在压缩内容上计算ETag
标头。 -
最顶层的其中一个,在
SessionMiddleware
(使用会话数据)和UpdateCacheMiddleware
(修改Vary
标头)之后。 -
在任何可能更改响应的中间件之前(它设置
Content-Length
标头)。在CommonMiddleware
之前出现的并且更改响应的中间件必须重置Content-Length
。接近顶部:当
APPEND_SLASH
或PREPEND_WWW
设置为True
时,它会重定向。在
SessionMiddleware
之后,如果您正在使用CSRF_USE_SESSIONS
。 -
在任何假定已处理 CSRF 攻击的视图中间件之前。
在
RemoteUserMiddleware
或任何其他可能执行登录(因此在调用中间件链之前轮换 CSRF 令牌)的身份验证中间件之前。在
SessionMiddleware
之后,如果您正在使用CSRF_USE_SESSIONS
。 -
在
SessionMiddleware
之后:使用会话存储。 -
在
SessionMiddleware
之后:可以使用基于会话的存储。 -
在任何修改
Vary
标头的中间件之后:该标头用于为缓存哈希键选择一个值。 -
应位于底部附近,因为它是一种最后手段类型的中间件。
-
应位于底部附近,因为它是一种最后手段类型的中间件。