csp头必须由开发者手动设置,gin不自动注入;需显式配置且策略须分环境——开发期可宽松(如启用'unsafe-inline'),生产环境须最小化授权并动态生成nonce防xss,禁用'unsafe-*'。

Content-Security-Policy头必须手动设置,Gin不自动注入
Gin本身不提供内置的CSP生成器或自动策略注入,Content-Security-Policy响应头需由开发者显式设置。依赖第三方中间件(如secure)虽能简化配置,但容易掩盖策略细节,导致上线后脚本加载失败或内联JS被静默拦截。
直接用c.Header()设置最可控,但nonce必须动态注入
静态写死Content-Security-Policy值会阻断所有内联脚本和未声明域名的资源加载;若页面含<script>console.log(1)</script>或使用CDN上的https://cdn.example.com/app.js,必须在策略中显式放行,且对内联脚本需配合nonce。
- 基础写法(无nonce,禁用所有内联脚本):
c.Header("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self'") - 带nonce的HTML模板需同步生成并传入:
Go中生成随机nonce:nonce := base64.StdEncoding.EncodeToString(randomBytes)
模板里写:<script nonce="{{.Nonce}}">...</script>
Header中对应写:c.Header("Content-Security-Policy", "default-src 'self'; script-src 'self' 'nonce-" + nonce + "'") - 避免硬编码nonce字符串——每次请求都应生成新值,否则失去防XSS意义
开发期和生产环境策略必须分离
本地开发时宽泛策略(如script-src 'unsafe-inline' 'unsafe-eval')方便调试,但绝不能带到生产环境。一旦启用CSP,浏览器会严格按策略执行,且控制台报错不中断JS运行,容易漏掉问题。
- 开发环境可临时放宽:
default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self' http://localhost:* - 生产环境必须最小化:
只允许明确域名的script-src、img-src等;object-src 'none'禁用Flash/Java插件;base-uri 'self'防止<base href="...">劫持;form-action 'self'阻止表单提交到第三方 - 上线前务必用
Content-Security-Policy-Report-Only头先行观察7天,收集违规报告再转为强制模式
第三方资源引入必须显式声明,CDN域名不能省略协议
CSP对协议敏感:https://cdn.jsdelivr.net和cdn.jsdelivr.net被视为不同源;'self'不包含子域,example.com和api.example.com需分别列出。
- 正确写法:
script-src 'self' https://cdn.jsdelivr.net https://unpkg.com - 错误写法:
script-src 'self' cdn.jsdelivr.net(缺少https://,会被拒绝加载) - 字体资源常被遗漏:
font-src 'self' https://fonts.gstatic.com - WebSocket连接需单独放行:
connect-src 'self' wss://api.example.com
CSP不是“设了就安全”,而是“设错就功能异常”。策略越细粒度,维护成本越高,但XSS防护强度也越高——关键在于把每个外部依赖都当成攻击面来审,而不是当成白名单来加。











