Content-Security-Policy需精准配置才有效:script-src至少含'self'且禁用'unsafe-inline'和'unsafe-eval',内联脚本改事件监听或用nonce;default-src不覆盖script-src等显式指令;开发期需放开'unsafe-eval'保HMR;connect-src等关键指令不可遗漏。
Content-Security-Policy 头该写哪些值才管用
光加个 content-security-policy 响应头不等于防住 xss,很多团队写了但没效果,是因为策略太宽或漏关键指令。核心是:只允许可信来源执行脚本、加载资源,其他一律拒绝。
常见错误现象:Refused to execute inline script 报错后直接删掉 script-src 'unsafe-inline' 就完事,结果页面白屏——说明没同步处理内联脚本和 eval 依赖。
-
script-src至少包含'self',禁用'unsafe-inline'和'unsafe-eval'(除非真有动态代码生成需求) - 如果用了内联事件(如
onclick="doSomething()"),必须改造成事件监听,否则策略会拦截 - 第三方 JS(如统计、广告)要显式列出域名,例如
https://cdn.example.com,不能只写example.com - 开发环境可加
report-uri或report-to收集违规日志,线上环境建议用Content-Security-Policy-Report-Only先灰度观察
Vue/React 项目里 inline-script 为什么总被拦
框架模板中看似“非脚本”的内容,比如 v-html、dangerouslySetInnerHTML、甚至某些组件库的 tooltip 渲染逻辑,都可能在运行时拼接并执行字符串,触发 CSP 拦截。
使用场景:后台富文本渲染、用户可编辑 HTML 的管理后台、低代码平台。
- 避免直接用
v-html插入未过滤的用户输入;改用 DOMPurify 等库清洗后再插入 - 如果必须支持内联逻辑,不要开
'unsafe-inline',而是用nonce—— 后端每次响应生成唯一值,写入<script nonce="abc123">和script-src 'nonce-abc123' - Webpack/Vite 构建时若用
html-webpack-plugin,可通过meta或templateParameters注入动态nonce,别硬编码
script-src 和 default-src 的优先级怎么算
很多人以为设了 default-src 'self' 就不用单独写 script-src,其实不是。CSP 是“指令覆盖”逻辑:更具体的指令永远优先于 default-src。
参数差异:default-src 只影响 script-src、style-src、img-src 等未显式声明的指令;但一旦写了 script-src,它就完全接管脚本加载规则,和 default-src 无关。
- 如果只设
default-src 'self',而没设script-src,那脚本策略就是'self' - 但如果同时写了
default-src 'none'和script-src 'self' https://cdn.js,脚本仍能加载,因为script-src覆盖了default-src -
base-uri、form-action、frame-ancestors这些指令不受default-src影响,必须单独配
本地开发时 CSP 导致热更新失效怎么办
Vite/HMR/Webpack Dev Server 默认用 eval 执行模块热替换代码,而 CSP 若禁用了 'unsafe-eval',就会卡住整个更新流程,表现为修改代码后页面不刷新、控制台报 Refused to evaluate a string as JavaScript。
性能 / 兼容性影响:开发期关 CSP 不影响安全,但上线必须打开;不同浏览器对 CSP v2/v3 支持略有差异,Chrome 最全,Safari 对 report-to 支持较晚。
- 开发环境响应头中彻底移除
Content-Security-Policy,或只保留script-src 'self'+'unsafe-eval' - 用环境变量区分:例如 Express 中
app.use((req, res, next) => { if (process.env.NODE_ENV === 'production') res.set('Content-Security-Policy', '...'); next(); }) - 别在 Nginx/Apache 配置里全局加 CSP,容易误伤 API 接口或静态资源返回头
最常被忽略的是 connect-src —— 如果前端用 fetch 调自己 API 却没在策略里声明,连请求都发不出去,还傻等接口超时。这个点上线前务必对着 Network 面板逐个核对请求协议+域名是否被放行。

















