揭秘django-csp的Nonce机制从request.csp_nonce到{% script %}模板标签安全使用内联脚本【免费下载链接】django-cspContent Security Policy for Django.项目地址: https://gitcode.com/gh_mirrors/dj/django-csp️django-csp是 Django 生态中用于实现CSPContent Security Policy内容安全策略的主流中间件而CSP Nonce一次性随机令牌正是它应对“内联脚本”这一 XSS 重灾区的核心武器。本文将带你快速理解request.csp_nonce的生成原理、{% script %}模板标签的用法以及如何安全地写内联 JavaScript。为什么需要 Nonce如果你的 CSP 策略里写了unsafe-inline那内联脚本是安全的——但XSS 攻击也就完全放行了。Nonce 的巧妙之处在于✅ 每个请求生成一个128 位随机值Base64 编码写入响应头✅ 只有带上该 nonce 的script标签才会被执行✅ 攻击者无法预测 nonce即使注入成功脚本也会被浏览器拦截 在 django-csp 中nonce 由 csp/middleware.py 里的_make_nonce方法生成每个请求只会生成一次后续读取都复用同一个值。第一步配置 NONCE 哨兵值django-csp 4.x 采用“哨兵值”方式在需要的指令里加入NONCE常量nonce 才会出现在响应头中。# settings.py from csp.constants import NONCE, SELF CONTENT_SECURITY_POLICY { DIRECTIVES: { default-src: [SELF], script-src: [SELF, NONCE], # 允许带 nonce 的内联脚本 style-src: [SELF, NONCE], frame-ancestors: [SELF], report-uri: /csp-report/, }, }⚠️关键机制只有当代码在响应处理完成之前真正读取了 nonce例如str(request.csp_nonce)响应头中才会包含nonce-xxx。没用到就不生成——这是 django-csp 的“懒生成”设计源码见 csp/middleware.py 的process_response。三种方式使用 request.csp_nonce方式一直接在模板中引用安装中间件后request对象上会自动挂一个惰性属性csp_noncescript nonce{{request.csp_nonce}} var hello world; /script方式二Context Processor 全局变量如果页面里有大量script标签可以把csp.context_processors.nonce加入context_processors模板中直接使用{{CSP_NONCE}}省去每个标签都写request.csp_nonce的麻烦。实现见 csp/context_processors.py。方式三{% script %} 模板标签推荐 ⭐人总会忘写nonce属性django-csp 提供了{% script %}标签每次渲染自动注入正确的 nonce永远不会漏。1. 注册模板库settings.pyTEMPLATES [{ OPTIONS: { libraries: { csp: csp.templatetags.csp, } } }]2. 在模板中使用{% load csp %} {% script typeapplication/javascript asyncFalse %} script var hello world; /script {% endscript %}渲染结果nonce 自动注入嵌套的script标签会被剥掉script nonce123456 typeapplication/javascript asyncfalsevar helloworld;/script✨ 小技巧标签体内用script包裹只是为了语法高亮渲染时会被自动移除。还支持src、id、defer、integrity等属性透传带src时正文会被忽略。实现见 csp/templatetags/csp.py 和 csp/utils.py。Jinja2 用户在 TEMPLATES 的extensions中加入csp.extensions.NoncedScript即可使用完全相同的{% script %}语法实现见 csp/extensions/init.py。Nonce 机制的 3 个安全细节细节说明懒生成未读取str(request.csp_nonce)前不产生随机值bool(request.csp_nonce)始终安全可用响应后读取会报错中间件写完响应头后再读 nonce 会抛出CSPNonceError帮你抓住“nonce 没进头部”的编程错误开发者工具里看不到出于安全考虑浏览器 DevTools 中不显示 nonce请用 “查看源代码”View Source验证如果你需要在响应前主动初始化 nonce比如自定义中间件要提前使用可以在MIDDLEWARE中CSPMiddleware之后加一段中间件执行str(getattr(request, csp_nonce, None))。完整接入清单 安装中间件MIDDLEWARE中加入csp.middleware.CSPMiddleware配置策略CONTENT_SECURITY_POLICY中给script-src加上NONCE模板改造用{% script %}标签或request.csp_nonce替换所有手写内联脚本上线验证查看源代码确认script nonce...与响应头nonce-...一致 至此你就可以在不使用unsafe-inline的前提下安全运行内联脚本把 XSS 攻击面再收窄一圈。更多配置细节可参考项目文档 docs/nonce.rst 与 docs/configuration.rst。【免费下载链接】django-cspContent Security Policy for Django.项目地址: https://gitcode.com/gh_mirrors/dj/django-csp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考