django-csp配置nonce后仍触发CSP内联脚本违规报错排查
问题原因
- 浏览器对
<script>标签的CSP校验优先匹配script-src-elem指令,仅当该指令未定义时才会回退匹配script-src、default-src规则。从报错信息看,当前响应头返回的script-src-elem规则仅包含'self'和https://cdn.jsdelivr.net/,没有携带合法nonce值,因此即使script标签写了nonce属性也会被拦截。 - 根因是django-csp的nonce注入范围配置不全:你仅在
CSP_INCLUDE_NONCE_IN中指定了script-src,nonce不会自动注入到script-src-elem指令中。从报错里的jsdelivr源可以判断项目中显式配置了CSP_SCRIPT_SRC_ELEM,当显式定义该参数时,它不会自动继承script-src的nonce规则,必须显式声明注入。 - 次要排查点:如果模板上下文中没有传入request对象,
{{ request.csp_nonce }}会渲染为空值,也会触发CSP拦截。
解决方法
- 修改
settings.py中的nonce注入范围配置,将script-src-elem加入注入列表:
# 原配置 # CSP_INCLUDE_NONCE_IN = ['script-src'] # 修改为 CSP_INCLUDE_NONCE_IN = ['script-src', 'script-src-elem']
- 校验模板上下文配置:打开
settings.py的TEMPLATES配置段,确认context_processors列表中包含django.template.context_processors.request,保证模板可以正常获取request对象生成nonce:
TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "APP_DIRS": True, "OPTIONS": { "context_processors": [ # 其他内置处理器 "django.template.context_processors.request", # 自定义处理器 ], }, }, ]
- 重启Django服务,硬刷新页面清除缓存后做两项校验:
- 打开浏览器开发者工具的网络面板,查看文档响应头的
Content-Security-Policy字段,确认script-src-elem规则中包含'nonce-'开头的随机串 - 查看页面源码中对应的内联script标签,确认标签上的nonce属性值和响应头中的nonce值完全一致
- 打开浏览器开发者工具的网络面板,查看文档响应头的
- 校验通过后内联脚本即可正常执行,不需要额外开启
unsafe-inline,也不需要手动配置哈希值。
内容的提问来源于stack exchange,提问作者kmnarendra
相关产品推荐
相关产品推荐

