csp 头需正确配置才有效,php 中 header() 易因输出提前、服务器覆盖或策略缺失而失效;script-src 应禁用 'unsafe-inline' 和 'unsafe-eval',改用外部脚本、哈希或 nonce 控制内联脚本。

CSP 头不是加了就安全,PHP 中直接用 header() 设置容易被绕过或失效,关键在策略写法、生效顺序和前端配合。
为什么 header('Content-Security-Policy: ...') 常常没效果
常见现象:PHP 脚本里写了 header(),但浏览器开发者工具里看不到 CSP,或报错仍允许执行内联脚本。
- 输出已开始(比如有空格、BOM、
echo或 HTML 前的换行),header()会静默失败 —— 检查 PHP 文件开头是否干净,用 UTF-8 无 BOM 编码 - Web 服务器(如 Nginx/Apache)或中间件(如 CDN、WAF)覆盖了 PHP 设置的头 —— 用浏览器 Network 面板看响应头真实值,优先级通常是:服务器 > PHP
- 策略中漏掉必需指令,比如只设了
script-src却没设default-src,导致其他资源(如图片、字体)被默认阻止
script-src 怎么写才不炸掉页面
这是最容易出问题的指令。放宽太狠等于没设,收太紧会让 jQuery、Vue、内联事件(onclick)、eval() 直接挂掉。
- 禁止
'unsafe-inline'和'unsafe-eval'—— 这是 CSP 的核心防线,但意味着你必须把所有内联<script></script>拆成外部文件,事件绑定改用addEventListener - 用哈希或 nonce 控制可信内联脚本:比如
script-src 'self' 'sha256-AbC123...',对应<script nonce="NcE4v...">...</script>,PHP 中需动态生成并传入模板 - 第三方库(如 Google Analytics)要显式加域名:
script-src 'self' https://www.googletagmanager.com https://cdn.jsdelivr.net,注意协议必须匹配
开发期用 Content-Security-Policy-Report-Only 试跑
直接上线 strict 策略风险高,先用报告模式观察真实请求行为,再收敛策略。
- 替换
header('Content-Security-Policy: ...')为header('Content-Security-Policy-Report-Only: script-src ...; report-uri /csp-report.php') -
/csp-report.php需接收 POST 请求,解析 JSON body(file_get_contents('php://input')),记录违规详情,注意防日志注入 - 报告里会暴露哪些脚本被拦、从哪来、什么 nonce 缺失——比猜更准
PHP 输出前必须检查的三件事
哪怕策略写对了,PHP 层一个疏忽就让整个 CSP 失效。
- 确保
header()在任何输出之前调用,可加if (headers_sent($file, $line)) { trigger_error("Headers already sent in $file on line $line", E_USER_ERROR); }快速定位 - 避免多个
header('Content-Security-Policy: ...')调用,后一次会覆盖前一次;建议集中在一个配置函数里生成完整策略字符串 - 如果用了输出缓冲(
ob_start()),CSP 头仍需在ob_start()后立即设置,不能等到ob_end_flush()时才发
最麻烦的不是写策略,而是前端代码里那些隐式依赖:动态 innerHTML 插入带 onclick 的 HTML、用 new Function() 构造逻辑、CDN 资源路径硬编码成 HTTP —— 这些不会报语法错,但会在 CSP 下静默失败。调试时别只盯 PHP,打开浏览器的 Console 和 Security 标签页看具体哪条指令被触发。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











