{"title":"跨站请求伪造保护","version":"6.0","locale":"zh-hans","docname":"ref/csrf","url":"/zh-hans/6.0/ref/csrf/","canonical":"https://djangodocs.dev/zh-hans/6.0/ref/csrf/","summary":"CSRF 中间件和模板标签提供了针对 跨站请求伪造 (Cross Site Request Forgeries) 的简单保护机制。这种类型的攻击发生在恶意网站包含一个链接、一个表单按钮或一些 JavaScript，旨在使用已登录用户的凭据在其浏览器中访问恶意网站以执行某些操作。还有一种相关的攻击类型叫做 '登录…","html":"<span id=\"cross-site-request-forgery-protection\"></span><h1>跨站请求伪造保护<a class=\"heading-anchor\" href=\"#module-django.middleware.csrf\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>CSRF 中间件和模板标签提供了针对 <a class=\"reference external\" href=\"https://owasp.org/www-community/attacks/csrf#overview\">跨站请求伪造 (Cross Site Request Forgeries)</a> 的简单保护机制。这种类型的攻击发生在恶意网站包含一个链接、一个表单按钮或一些 JavaScript，旨在使用已登录用户的凭据在其浏览器中访问恶意网站以执行某些操作。还有一种相关的攻击类型叫做 '登录 CSRF'，其中攻击者的网站会欺骗用户的浏览器，以使用其他用户的凭据登录到某个站点，这也得到了保护。</p>\n<p>对抗 CSRF 攻击的第一道防线是确保 GET 请求（以及其他按照 <span class=\"target\" id=\"index-6\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1\"><strong>RFC 9110 Section 9.2.1</strong></a> 定义的 '安全' 方法）是无副作用的。然后，可以按照 <a class=\"reference internal\" href=\"/zh-hans/6.0/howto/csrf/#using-csrf\"><span class=\"std std-ref\">如何使用 Django 提供的 CSRF 防护功能</span></a> 中概述的步骤来保护通过 '不安全' 方法（如 POST、PUT 和 DELETE）的请求。</p>\n<section id=\"how-it-works\">\n<span id=\"how-csrf-works\"></span><h2>工作方式<a class=\"heading-anchor\" href=\"#how-it-works\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>CSRF 保护是基于以下几点：</p>\n<ol class=\"arabic\">\n<li><p>CSRF cookie 是一个随机的秘密值，其他网站无法访问。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware</span></code> 在每次调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.middleware.csrf.get_token()</span></code> 时都会将这个 cookie 与响应一起发送。出于安全原因，每当用户登录时，这个秘密值的值都会更改。</p>\n</li>\n<li><p>一个名为 'csrfmiddlewaretoken' 的隐藏表单字段，出现在所有发送的 POST 表单中。</p>\n<p>为了防止 <a class=\"reference external\" href=\"https://www.breachattack.com/\">BREACH</a> 攻击，这个字段的值不仅仅是秘密值。它在每个响应中都使用一个掩码进行不同方式的混淆。每次调用 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_token()</span></code> 时，都会随机生成一个掩码，因此表单字段的值每次都不同。</p>\n<p>这部分由 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/templates/builtins/#std-templatetag-csrf_token\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">csrf_token</span></code></a> 模板标签完成。</p>\n</li>\n<li><p>对于所有不使用 HTTP GET、HEAD、OPTIONS 或 TRACE 的传入请求，必须存在一个 CSRF cookie，并且“csrfmiddlewaretoken”字段必须存在且正确。如果不存在，用户将得到一个 403 错误。</p>\n<p>当验证“csrfmiddlewaretoken”字段值时，只有密钥，而不是完整的令牌，会与 cookie 值中的密钥进行比较。这允许使用不断变化的令牌。虽然每个请求都可能使用自己的令牌，但密钥对所有请求都是通用的。</p>\n<p>这个检查是由 <code class=\"docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware</span></code> 完成的。</p>\n</li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware</span></code> 根据当前主机和 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_TRUSTED_ORIGINS</span></code></a> 的设置，验证 <a class=\"reference external\" href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin\">Origin header</a> ，如果是由浏览器提供的。这提供了对跨子域攻击的保护。</p></li>\n<li><p>此外，对于 HTTPS 请求，如果没有提供 <code class=\"docutils literal notranslate\"><span class=\"pre\">Origin</span></code> 头，<code class=\"docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware</span></code> 会执行严格的来源检查。这意味着，即使一个子域可以设置或修改你的域名上的 cookie，它也不能强迫用户向你的应用程序发布，因为该请求不会来自你自己的确切域名。</p>\n<p>这也解决了在 HTTPS 下使用独立于会话的密钥时可能出现的中间人攻击问题，这是因为 HTTP <code class=\"docutils literal notranslate\"><span class=\"pre\">Set-Cookie</span></code> 头会被客户接受（不幸的是），即使他们在 HTTPS 下与一个网站对话。对 HTTP 请求不进行 Referer 检查，因为 HTTP 下 <code class=\"docutils literal notranslate\"><span class=\"pre\">Referer</span></code> 头的存在不够可靠）。</p>\n<p>如果设置了 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_DOMAIN\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_DOMAIN</span></code></a> 设置，则会将 referer 与之进行比较。你可以通过包含一个前导点号来允许跨子域请求。例如，<code class=\"docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_DOMAIN</span> <span class=\"pre\">=</span> <span class=\"pre\">'.example.com'</span></code> 将允许来自 <code class=\"docutils literal notranslate\"><span class=\"pre\">www.example.com</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">api.example.com</span></code> 的 POST 请求。如果没有设置，那么 referer 必须与 HTTP <code class=\"docutils literal notranslate\"><span class=\"pre\">Host</span></code> 头匹配。</p>\n<p>通过 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_TRUSTED_ORIGINS</span></code></a> 设置，可以将接受的 referer 扩展到当前主机或 cookie 域之外。</p>\n</li>\n</ol>\n<p>这确保了只有源自受信任域的表单才能用于 POST 回数据。</p>\n<p>它故意忽略 GET 请求（以及其他被 <span class=\"target\" id=\"index-7\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1\"><strong>RFC 9110 Section 9.2.1</strong></a> 定义为 '安全' 的请求）。这些请求不应该具有潜在的危险副作用，因此通过 GET 请求进行的 CSRF 攻击应该是无害的。<span class=\"target\" id=\"index-8\"></span><a class=\"rfc reference external\" href=\"https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1\"><strong>RFC 9110 Section 9.2.1</strong></a> 将 POST、PUT 和 DELETE 定义为 '不安全'，而所有其他方法也被假定为不安全，以提供最大的保护。</p>\n<p>CSRF 保护不能防止中间人攻击，所以使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/security/#security-recommendation-ssl\"><span class=\"std std-ref\">HTTPS</span></a> 与 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/middleware/#http-strict-transport-security\"><span class=\"std std-ref\">HTTP 严格传输安全</span></a>。它还假设 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/security/#host-headers-virtual-hosting\"><span class=\"std std-ref\">验证 HOST 头</span></a> 和你的网站上没有任何 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/security/#cross-site-scripting\"><span class=\"std std-ref\">跨站脚本漏洞</span></a> （因为 XSS 漏洞已经让攻击者做了 CSRF 漏洞允许的任何事情，甚至更糟）。</p>\n<aside class=\"admonition-removing-the-referer-header admonition\">\n<p class=\"admonition-title\">删除 <code class=\"docutils literal notranslate\"><span class=\"pre\">Referer</span></code> 头</p>\n<p>为了避免向第三方网站透露 referrer URL，你可能想在你的网站的 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;a&gt;</span></code> 标签上 <a class=\"reference external\" href=\"https://www.w3.org/TR/referrer-policy/#referrer-policy-delivery\">禁用 referrer</a> 。例如，你可以使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;meta</span> <span class=\"pre\">name=&quot;referrer&quot;</span> <span class=\"pre\">content=&quot;no-referrer&quot;&gt;</span></code> 标签或包含 <code class=\"docutils literal notranslate\"><span class=\"pre\">Referrer-Policy:</span> <span class=\"pre\">no-referrer</span></code> 头。由于 CSRF 保护对 HTTPS 请求进行严格的 referer 检查，这些技术会在使用“不安全”方法的请求上导致 CSRF 失败。取而代之的是，使用诸如 <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;a</span> <span class=\"pre\">rel=&quot;noreferrer&quot;</span> <span class=\"pre\">...&gt;&quot;</span></code> 这样的替代品来链接第三方网站。</p>\n</aside>\n</section>\n<section id=\"limitations\">\n<span id=\"csrf-limitations\"></span><h2>限制<a class=\"heading-anchor\" href=\"#limitations\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>站点内的子域名将能够在整个域上为客户端设置 cookie。通过设置 cookie 并使用相应的令牌，子域名将能够绕过 CSRF 保护。避免这种情况的唯一方法是确保子域名由可信任的用户控制（或者至少不能设置 cookie）。请注意，即使没有 CSRF，还存在其他漏洞，例如会话固定，这些漏洞会使将子域名交给不受信任的方可能不是一个好主意，而且这些漏洞在当前的浏览器中不能轻易修复。</p>\n</section>\n<section id=\"module-django.views.decorators.csrf\">\n<span id=\"utilities\"></span><h2>实用程序<a class=\"heading-anchor\" href=\"#module-django.views.decorators.csrf\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>下面的例子假设你使用的是基于函数的视图。如果你正在使用基于类的视图，你可以参考 <a class=\"reference internal\" href=\"/zh-hans/6.0/topics/class-based-views/intro/#id1\"><span class=\"std std-ref\">装饰基于类的视图</span></a>。</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.views.decorators.csrf.csrf_exempt\">\n<span class=\"sig-name descname\"><span class=\"pre\">csrf_exempt</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.views.decorators.csrf.csrf_exempt\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>该装饰器标记着一个视图被免除了中间件所确保的保护。例如：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.http</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">HttpResponse</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.decorators.csrf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">csrf_exempt</span>\n\n\n<span class=\"nd\">@csrf_exempt</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"k\">return</span> <span class=\"n\">HttpResponse</span><span class=\"p\">(</span><span class=\"s2\">&quot;Hello world&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.views.decorators.csrf.csrf_protect\">\n<span class=\"sig-name descname\"><span class=\"pre\">csrf_protect</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.views.decorators.csrf.csrf_protect\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Decorator that provides the protection of\n<a class=\"reference internal\" href=\"/zh-hans/6.0/ref/middleware/#django.middleware.csrf.CsrfViewMiddleware\" title=\"django.middleware.csrf.CsrfViewMiddleware\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware</span></code></a> to a view.</p>\n<p>用法：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.decorators.csrf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">csrf_protect</span>\n\n\n<span class=\"nd\">@csrf_protect</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s2\">&quot;a_template.html&quot;</span><span class=\"p\">,</span> <span class=\"n\">c</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.views.decorators.csrf.requires_csrf_token\">\n<span class=\"sig-name descname\"><span class=\"pre\">requires_csrf_token</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.views.decorators.csrf.requires_csrf_token\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>通常情况下，如果 <code class=\"docutils literal notranslate\"><span class=\"pre\">CsrfViewMiddleware.process_view</span></code> 或类似 <code class=\"docutils literal notranslate\"><span class=\"pre\">csrf_protect</span></code> 这样的等价物没有运行， <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/templates/builtins/#std-templatetag-csrf_token\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">csrf_token</span></code></a> 模板标签将无法工作。视图装饰器 <code class=\"docutils literal notranslate\"><span class=\"pre\">requires_csrf_token</span></code> 可以用来确保模板标签工作。这个装饰器的工作原理与 <code class=\"docutils literal notranslate\"><span class=\"pre\">csrf_protect</span></code> 类似，但绝不会拒绝接收到的请求。</p>\n<p>举例：</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.shortcuts</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">render</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.views.decorators.csrf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">requires_csrf_token</span>\n\n\n<span class=\"nd\">@requires_csrf_token</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_view</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">):</span>\n    <span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"p\">{}</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">return</span> <span class=\"n\">render</span><span class=\"p\">(</span><span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"s2\">&quot;a_template.html&quot;</span><span class=\"p\">,</span> <span class=\"n\">c</span><span class=\"p\">)</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.views.decorators.csrf.ensure_csrf_cookie\">\n<span class=\"sig-name descname\"><span class=\"pre\">ensure_csrf_cookie</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">view</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.views.decorators.csrf.ensure_csrf_cookie\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>该装饰器强制视图发送 CSRF cookie。</p>\n</dd></dl>\n\n</section>\n<section id=\"settings\">\n<h2>配置<a class=\"heading-anchor\" href=\"#settings\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>一些配置可以用来控制Django 的 CSRF 行为：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_AGE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_AGE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_DOMAIN\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_DOMAIN</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_HTTPONLY\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_HTTPONLY</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_NAME</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_PATH\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_PATH</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_SAMESITE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_SAMESITE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_COOKIE_SECURE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_COOKIE_SECURE</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_FAILURE_VIEW\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_FAILURE_VIEW</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_HEADER_NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_HEADER_NAME</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_TRUSTED_ORIGINS</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_USE_SESSIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_USE_SESSIONS</span></code></a></p></li>\n</ul>\n</section>\n<section id=\"frequently-asked-questions\">\n<h2>常问问题<a class=\"heading-anchor\" href=\"#frequently-asked-questions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"is-posting-an-arbitrary-csrf-token-pair-cookie-and-post-data-a-vulnerability\">\n<h3>可以提交任意的 CSRF 令牌对（cookie 和 POST 数据）是漏洞吗？<a class=\"heading-anchor\" href=\"#is-posting-an-arbitrary-csrf-token-pair-cookie-and-post-data-a-vulnerability\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>不，这是设计好的。如果没有中间人攻击，攻击者就没有办法向受害者的浏览器发送 CSRF 令牌 cookie，所以成功的攻击需要通过 XSS 或类似的方式获得受害者浏览器的 cookie，在这种情况下，攻击者通常不需要 CSRF 攻击。</p>\n<p>一些安全审计工具将此标记为问题，但如前所述，攻击者无法窃取用户浏览器的 CSRF cookie。使用 Firebug、Chrome 开发工具等“窃取”或修改 <em>自己的</em> 令牌并不是漏洞。</p>\n</section>\n<section id=\"is-it-a-problem-that-django-s-csrf-protection-isn-t-linked-to-a-session-by-default\">\n<h3>Django 的 CSRF 保护默认不与会话关联，是不是有问题？<a class=\"heading-anchor\" href=\"#is-it-a-problem-that-django-s-csrf-protection-isn-t-linked-to-a-session-by-default\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>不，这是设计好的。不将 CSRF 保护与会话联系起来，就可以在诸如 <em>pastebin</em> 这样允许匿名用户提交的网站上使用保护，而这些用户并没有会话。</p>\n<p>如果你希望在用户的会话中存储 CSRF 令牌，请使用 <a class=\"reference internal\" href=\"/zh-hans/6.0/ref/settings/#std-setting-CSRF_USE_SESSIONS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">CSRF_USE_SESSIONS</span></code></a> 设置。</p>\n</section>\n<section id=\"why-might-a-user-encounter-a-csrf-validation-failure-after-logging-in\">\n<h3>为什么用户登录后会遇到 CSRF 验证失败？<a class=\"heading-anchor\" href=\"#why-might-a-user-encounter-a-csrf-validation-failure-after-logging-in\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>出于安全考虑，每次用户登录时，CSRF 令牌都会轮换。任何在登录前生成表单的页面都会有一个旧的、无效的 CSRF 令牌，需要重新加载。如果用户在登录后使用后退按钮或在不同的浏览器标签页中登录，可能会发生这种情况。</p>\n</section>\n</section>","rootId":"module-django.middleware.csrf","toc":[{"title":"工作方式","anchor":"how-it-works","children":[]},{"title":"限制","anchor":"limitations","children":[]},{"title":"实用程序","anchor":"module-django.views.decorators.csrf","children":[]},{"title":"配置","anchor":"settings","children":[]},{"title":"常问问题","anchor":"frequently-asked-questions","children":[{"title":"可以提交任意的 CSRF 令牌对（cookie 和 POST 数据）是漏洞吗？","anchor":"is-posting-an-arbitrary-csrf-token-pair-cookie-and-post-data-a-vulnerability","children":[]},{"title":"Django 的 CSRF 保护默认不与会话关联，是不是有问题？","anchor":"is-it-a-problem-that-django-s-csrf-protection-isn-t-linked-to-a-session-by-default","children":[]},{"title":"为什么用户登录后会遇到 CSRF 验证失败？","anchor":"why-might-a-user-encounter-a-csrf-validation-failure-after-logging-in","children":[]}]}],"breadcrumbs":[{"docname":"ref/index","title":"API 参考","url":"/zh-hans/6.0/ref/"}],"prev":{"docname":"ref/csp","title":"Content Security Policy","url":"/zh-hans/6.0/ref/csp/"},"next":{"docname":"ref/databases","title":"数据库","url":"/zh-hans/6.0/ref/databases/"},"formats":{"html":"/zh-hans/6.0/ref/csrf/","markdown":"/zh-hans/6.0/ref/csrf.md","json":"/zh-hans/6.0/ref/csrf.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/ref/csrf.txt","official":"https://docs.djangoproject.com/zh-hans/6.0/ref/csrf/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}