{"title":"如何使用 Django 的内容安全策略","version":"6.1","locale":"zh-hans","docname":"howto/csp","url":"/zh-hans/6.1/howto/csp/","canonical":"https://djangodocs.dev/zh-hans/6.1/howto/csp/","summary":"要在Django项目中启用内容安全策略（CSP）：将CSP中间件添加到中间件设置中、在settings.py文件中，使用 SECURE_CSP 或 SECURE_CSP_REPORT_ONLY…","html":"<h1>如何使用 Django 的内容安全策略<a class=\"heading-anchor\" href=\"#how-to-use-django-s-content-security-policy\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<section id=\"basic-config\">\n<span id=\"csp-config\"></span><h2>基础配置<a class=\"heading-anchor\" href=\"#basic-config\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>要在Django项目中启用内容安全策略（CSP）：</p>\n<ol class=\"arabic\">\n<li><p>将CSP中间件添加到 <code class=\"xref std std-setting docutils literal notranslate\">中间件</code> 设置中：</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>MIDDLEWARE <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"s2\">&quot;django.middleware.csp.ContentSecurityPolicyMiddleware&quot;</span><span class=\"p\">,</span>\n    <span class=\"c1\"># ...</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n<li><p>在settings.py文件中，使用 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-SECURE_CSP\"><code class=\"xref std std-setting docutils literal notranslate\">SECURE_CSP</code></a> 或 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-SECURE_CSP_REPORT_ONLY\"><code class=\"xref std std-setting docutils literal notranslate\">SECURE_CSP_REPORT_ONLY</code></a> （或两者都使用）来配置CSP策略。<a class=\"reference internal\" href=\"/zh-hans/6.1/ref/csp/#csp-settings\"><span class=\"std std-ref\">CSP设置文档</span></a> 提供了关于这两者之间差异的更多详细信息：</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=\"nn\">django.utils.csp</span> <span class=\"kn\">import</span> CSP\n\n<span class=\"c1\"># To enforce a CSP policy:</span>\nSECURE_CSP <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default-src&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>CSP<span class=\"o\">.</span>SELF<span class=\"p\">],</span>\n    <span class=\"c1\"># Add more directives to be enforced.</span>\n<span class=\"p\">}</span>\n\n<span class=\"c1\"># Or for report-only mode:</span>\nSECURE_CSP_REPORT_ONLY <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default-src&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>CSP<span class=\"o\">.</span>SELF<span class=\"p\">],</span>\n    <span class=\"c1\"># Add more directives as needed.</span>\n    <span class=\"s2\">&quot;report-uri&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;/path/to/reports-endpoint/&quot;</span><span class=\"p\">,</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</li>\n</ol>\n</section>\n<section id=\"nonce-config\">\n<span id=\"csp-nonce-config\"></span><h2>Nonce配置<a class=\"heading-anchor\" href=\"#nonce-config\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>要在CSP策略中使用一次性随机数，即Nonce，除了基本配置外，你还需要：</p>\n<ol class=\"arabic\">\n<li><p>在CSP设置中包含 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/csp/#django.utils.csp.CSP.NONCE\" title=\"django.utils.csp.CSP.NONCE\"><code class=\"xref py py-attr docutils literal notranslate\">NONCE</code></a> 占位符值。这仅适用于 <code class=\"docutils literal notranslate\">script-src</code> 或 <code class=\"docutils literal notranslate\">style-src</code> 指令：</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=\"nn\">django.utils.csp</span> <span class=\"kn\">import</span> CSP\n\nSECURE_CSP <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s2\">&quot;default-src&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>CSP<span class=\"o\">.</span>SELF<span class=\"p\">],</span>\n    <span class=\"c1\"># Allow self-hosted scripts and script tags with matching `nonce` attr.</span>\n    <span class=\"s2\">&quot;script-src&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>CSP<span class=\"o\">.</span>SELF<span class=\"p\">,</span> CSP<span class=\"o\">.</span>NONCE<span class=\"p\">],</span>\n    <span class=\"c1\"># Example of the less secure &#39;unsafe-inline&#39; option.</span>\n    <span class=\"s2\">&quot;style-src&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>CSP<span class=\"o\">.</span>SELF<span class=\"p\">,</span> CSP<span class=\"o\">.</span>UNSAFE_INLINE<span class=\"p\">],</span>\n<span class=\"p\">}</span>\n</code></pre></div>\n</li>\n<li><p>将 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/templates/api/#django.template.context_processors.csp\" title=\"django.template.context_processors.csp\"><code class=\"xref py py-func docutils literal notranslate\">csp()</code></a> 上下文处理器添加到你的 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\">TEMPLATES</code></a> 设置中。这样，生成的随机数就会作为``csp_nonce``上下文变量在 Django 模板中可用：</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>TEMPLATES <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;BACKEND&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.template.backends.django.DjangoTemplates&quot;</span><span class=\"p\">,</span>\n        <span class=\"s2\">&quot;OPTIONS&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;context_processors&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span>\n                <span class=\"c1\"># ...</span>\n                <span class=\"s2\">&quot;django.template.context_processors.csp&quot;</span><span class=\"p\">,</span>\n            <span class=\"p\">],</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n</li>\n<li><p>In your templates, add the nonce to elements that require it:</p>\n<p>For inline <code class=\"docutils literal notranslate\">&lt;style&gt;</code> or <code class=\"docutils literal notranslate\">&lt;script&gt;</code> tags, use the <code class=\"docutils literal notranslate\">csp_nonce</code> context\nvariable directly:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">style</span> <span class=\"na\">nonce</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">csp_nonce</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n  <span class=\"c\">/* These inline styles will be allowed. */</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">style</span><span class=\"p\">&gt;</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">script</span> <span class=\"na\">nonce</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{{</span> <span class=\"nv\">csp_nonce</span> <span class=\"cp\">}}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n  <span class=\"c1\">// This inline JavaScript will be allowed.</span>\n<span class=\"p\">&lt;/</span><span class=\"nt\">script</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>For external <code class=\"docutils literal notranslate\">&lt;script src=&quot;...&quot;&gt;</code> and <code class=\"docutils literal notranslate\">&lt;link rel=&quot;stylesheet&quot;&gt;</code>\nelements, use the <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/templates/builtins/#std-templatetag-csp_nonce_attr\"><code class=\"xref std std-ttag docutils literal notranslate\">csp_nonce_attr</code></a> template tag:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"p\">&lt;</span><span class=\"nt\">script</span> <span class=\"na\">src</span><span class=\"o\">=</span><span class=\"s\">&quot;/path/to/script.js&quot;</span> <span class=\"cp\">{%</span> <span class=\"k\">csp_nonce_attr</span> <span class=\"cp\">%}</span><span class=\"p\">&gt;&lt;/</span><span class=\"nt\">script</span><span class=\"p\">&gt;</span>\n<span class=\"p\">&lt;</span><span class=\"nt\">link</span> <span class=\"na\">rel</span><span class=\"o\">=</span><span class=\"s\">&quot;stylesheet&quot;</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;/path/to/style.css&quot;</span> <span class=\"cp\">{%</span> <span class=\"k\">csp_nonce_attr</span> <span class=\"cp\">%}</span><span class=\"p\">&gt;</span>\n</code></pre></div>\n<p>To render a <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/forms/media/#django.forms.Media\" title=\"django.forms.Media\"><code class=\"xref py py-class docutils literal notranslate\">Media</code></a> object's assets with the nonce\napplied to each element, pass the object to the <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/templates/builtins/#std-templatetag-csp_nonce_attr\"><code class=\"xref std std-ttag docutils literal notranslate\">csp_nonce_attr</code></a> tag:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">csp_nonce_attr</span> <span class=\"nv\">form.media</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<aside class=\"version-note version-changed\" data-version=\"6.1\" role=\"note\">\n<p class=\"version-note-title\">Changed in Django 6.1</p><p>The <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/templates/builtins/#std-templatetag-csp_nonce_attr\"><code class=\"xref std std-ttag docutils literal notranslate\">csp_nonce_attr</code></a> template tag was added, including support for\nrendering <a class=\"reference internal\" href=\"/zh-hans/6.1/topics/forms/media/#django.forms.Media\" title=\"django.forms.Media\"><code class=\"xref py py-class docutils literal notranslate\">Media</code></a> objects.</p>\n</aside>\n</li>\n</ol>\n<aside class=\"admonition-caching-and-nonce-reuse admonition\" role=\"note\">\n<p class=\"admonition-title\">缓存与Nonce复用</p>\n<p>当模板中使用nonce时，<a class=\"reference internal\" href=\"/zh-hans/6.1/ref/middleware/#django.middleware.csp.ContentSecurityPolicyMiddleware\" title=\"django.middleware.csp.ContentSecurityPolicyMiddleware\"><code class=\"xref py py-class docutils literal notranslate\">ContentSecurityPolicyMiddleware</code></a> 会自动处理生成唯一的nonce，并将相应的 <code class=\"docutils literal notranslate\">nonce-&lt;value&gt;</code> 源表达式插入到 <code class=\"docutils literal notranslate\">Content-Security-Policy</code> （或 <code class=\"docutils literal notranslate\">Content-Security-Policy-Report-Only</code>）头部中。</p>\n<p>为确保行为正确，请确保HTML和头部（header）都在同一请求中生成，而不是从缓存中获取。有关实现细节和重要的缓存注意事项，请参阅 <a class=\"reference internal\" href=\"/zh-hans/6.1/ref/csp/#csp-nonce\"><span class=\"std std-ref\">Nonce usage</span></a> 的参考文档。</p>\n</aside>\n</section>","rootId":"how-to-use-django-s-content-security-policy","toc":[{"title":"基础配置","anchor":"basic-config","children":[]},{"title":"Nonce配置","anchor":"nonce-config","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"如何引导","url":"/zh-hans/6.1/howto/"}],"prev":{"docname":"howto/auth-remote-user","title":"使用 REMOTE_USER 进行身份验证","url":"/zh-hans/6.1/howto/auth-remote-user/"},"next":{"docname":"howto/csrf","title":"如何使用 Django 提供的 CSRF 防护功能","url":"/zh-hans/6.1/howto/csrf/"},"formats":{"html":"/zh-hans/6.1/howto/csp/","markdown":"/zh-hans/6.1/howto/csp.md","json":"/zh-hans/6.1/howto/csp.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/howto/csp.txt","official":"https://docs.djangoproject.com/zh-hans/6.1/howto/csp/","inVersions":["6.1","6.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}