Django中CSP Header中间件失效问题及配置咨询
Django CSP配置问题:script/style源设置、unsafe-inline与style-src-elem解析及错误修复
问题背景
在Django项目的settings.py中配置CSP(内容安全策略)时,遇到Chrome控制台报错问题,需要明确script/style源的设置方法,理解'unsafe-inline'、style-src-elem等参数的作用,并找到更简便的配置方式。当前配置代码如下:
MIDDLEWARE = [ 'csp.middleware.CSPMiddleware', ...] CSP_DEFAULT_SRC = ("'none'", ) CSP_STYLE_SRC = ("'self'", "'unsafe-inline'", "fonts.googleapis.com", "'unsafe-inline'", 'https://stackpath.bootstrapcdn.com') CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'", "ajax.googleapis.com", "www.googletagmanager.com", "www.google-analytics.com", 'https://cdn.jsdelivr.net','https://code.jquery.com', "'unsafe-inline'", 'https//ajax.cloudflare.com', "'unsafe-inline'", 'http://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/') CSP_IMG_SRC = ("'self'", "data:", "www.googletagmanager.com", "www.google-analytics.com") CSP_FONT_SRC = ("'self'", "'unsafe-inline'", "fonts.gstatic.com",'https://fonts.cdnfonts.com', 'https://stackpath.bootstrapcdn.com') CSP_CONNECT_SRC = ("'self'", ) CSP_OBJECT_SRC = ("'none'", ) CSP_BASE_URI = ("'none'", ) CSP_FRAME_ANCESTORS = ("'none'", ) CSP_FORM_ACTION = ("'self'", ) CSP_INCLUDE_NONCE_IN = ('script-src','script-src-elem') CSP_REPORT_ONLY = True
核心参数解析
'unsafe-inline':CSP默认禁止所有内联脚本/样式(包括<script>标签内代码、元素onclick事件、<style>标签内样式、元素style属性),添加该值就是放宽限制允许内联内容。但这会降低CSP安全性,优先用nonce或hash替代,仅在无其他方案时使用。style-src-elem:专门管控通过<link>标签引入的外部样式表来源,是style-src的细分规则。style-src覆盖所有样式来源(内联、属性、外部),而style-src-elem仅针对外部样式元素。script-src-elem:与style-src-elem对应,专门管控通过<script>标签引入的外部脚本来源,script-src则覆盖所有脚本来源(内联、事件处理器、外部)。
当前配置的问题及修复步骤
- 重复的
'unsafe-inline':CSP_STYLE_SRC和CSP_SCRIPT_SRC中多次重复该值,完全冗余,每个源列表保留一次即可。 - 错误的URL:
CSP_SCRIPT_SRC里的'https//ajax.cloudflare.com'缺少冒号,应改为'https://ajax.cloudflare.com',否则该源无法被识别,触发CSP错误。 - 无用的
'unsafe-inline':CSP_FONT_SRC中添加该值完全多余,字体源是文件资源,不需要允许内联代码,直接删除。 - Nonce配置未落地:配置了
CSP_INCLUDE_NONCE_IN但未在模板中实际使用nonce。若想用nonce替代'unsafe-inline'(更安全),需:- 在
TEMPLATES的上下文处理器中添加'csp.context_processors.nonce' - 在模板的
<script>和<style>标签中添加nonce="{{ csp_nonce }}"属性 - 之后可移除
'unsafe-inline',nonce是验证内联内容的安全方式
- 在
修正后的配置示例:
MIDDLEWARE = [ 'csp.middleware.CSPMiddleware', # 其他中间件... ] CSP_DEFAULT_SRC = ("'none'",) CSP_STYLE_SRC = ( "'self'", # 启用nonce则删除下一行 "'unsafe-inline'", "fonts.googleapis.com", "https://stackpath.bootstrapcdn.com" ) CSP_SCRIPT_SRC = ( "'self'", # 启用nonce则删除下一行 "'unsafe-inline'", "ajax.googleapis.com", "www.googletagmanager.com", "www.google-analytics.com", "https://cdn.jsdelivr.net", "https://code.jquery.com", "https://ajax.cloudflare.com", # 修正URL "http://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/" ) CSP_IMG_SRC = ("'self'", "data:", "www.googletagmanager.com", "www.google-analytics.com") CSP_FONT_SRC = ( "'self'", "fonts.gstatic.com", "https://fonts.cdnfonts.com", "https://stackpath.bootstrapcdn.com" ) CSP_CONNECT_SRC = ("'self'",) CSP_OBJECT_SRC = ("'none'",) CSP_BASE_URI = ("'none'",) CSP_FRAME_ANCESTORS = ("'none'",) CSP_FORM_ACTION = ("'self'",) # 启用nonce的额外配置 CSP_INCLUDE_NONCE_IN = ('script-src', 'style-src') TEMPLATES = [ { # 其他模板配置... 'OPTIONS': { 'context_processors': [ # 其他处理器... 'csp.context_processors.nonce', ], }, }, ] CSP_REPORT_ONLY = True
模板中使用nonce的示例:
<script nonce="{{ csp_nonce }}"> // 内联脚本代码 </script> <link rel="stylesheet" nonce="{{ csp_nonce }}" href="/static/css/main.css">
简化CSP配置的技巧
- 利用
REPORT_ONLY模式测试:先开启CSP_REPORT_ONLY = True,此时CSP仅报错不拦截,收集所有需要的源后再调整配置,避免直接强制生效导致网站功能异常。 - 自动注入nonce:使用django-csp提供的
csp.context_processors.nonce,无需手动在每个视图生成nonce,模板直接调用{{ csp_nonce }}即可。 - 分组同类源:将同一服务商的源(如谷歌相关、CDN相关)放在一起,便于维护。
- 合理使用默认源:若大部分资源来自同一域名,可调整
CSP_DEFAULT_SRC减少单独配置的源数量(当前设为'none'符合严格安全要求,可保持)。
内容的提问来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

