Django 2升4后配置CSP策略加载Google字体遇阻问题排查
Django 升级后CSP拦截Google字体的问题分析与解决
核心原因:中间件与meta标签CSP的冲突
你添加了csp.middleware.CSPMiddleware,这个中间件的核心作用是生成HTTP头形式的CSP规则——哪怕你没在Django settings里配置任何CSP,它也会自动生成默认规则(比如default-src 'self' 'nonce-xxx')。而浏览器会同时生效HTTP头CSP和meta标签CSP,两者规则是叠加执行(逻辑与),取最严格的限制。
这直接导致了你的两个异常点:
- 你在meta标签里设置的
style-src-elem被HTTP头的默认规则覆盖,浏览器识别不到该指令,只能 fallback 到default-src; - Google字体的样式表域名
https://fonts.googleapis.com不在默认的default-src范围内,因此被拦截。
具体解决方案
方案1:移除中间件,纯meta标签配置
如果你坚持用meta标签管理CSP,直接从MIDDLEWARE列表里删掉csp.middleware.CSPMiddleware——这个中间件对你的配置方式来说完全多余,反而会生成冲突的HTTP头CSP。
然后确保meta标签的规则完整:
<meta http-equiv="Content-Security-Policy" content=" default-src 'self' 'nonce-d0R7xtS9JR5LNg6UqQ5FCg=='; style-src-elem 'self' https://fonts.googleapis.com 'nonce-d0R7xtS9JR5LNg6UqQ5FCg=='; font-src 'self' https://fonts.gstatic.com; ">
style-src-elem必须显式包含https://fonts.googleapis.com,这是Google字体样式表的托管域名;font-src要添加https://fonts.gstatic.com,字体文件实际存储在这个域名下;- 保证nonce值和你模板中内嵌样式/脚本的nonce完全一致。
方案2:保留中间件,用django-csp配置代替meta标签
meta标签CSP存在局限性(不支持部分指令、优先级低于HTTP头),更推荐直接用django-csp的settings配置:
# settings.py CSP_DEFAULT_SRC = ["'self'"] # 允许样式表来源 CSP_STYLE_SRC_ELEM = ["'self'", "https://fonts.googleapis.com", "'nonce-%s'" % CSP_NONCE_SECRET] # 允许字体文件来源 CSP_FONT_SRC = ["'self'", "https://fonts.gstatic.com"]
这种方式下,中间件会自动生成正确的HTTP头CSP,无需手动写meta标签,也不会有规则冲突的问题。
额外排查点
如果按上面配置后还是报错,试试:
- 强制刷新页面(Ctrl+F5),清除浏览器缓存的旧CSP规则;
- 检查浏览器开发者工具的「网络」面板,确认请求的Google字体样式表域名和你配置的完全一致。
内容的提问来源于stack exchange,提问作者zacniewski
相关产品推荐
相关产品推荐

