全局安全响应头必须配置在httpd.conf或conf.d下独立文件中且位于外;禁用.htaccess方式;优先用Header always set;关键头包括HSTS、X-Frame-Options、X-Content-Type-Options、X-XSS-Protection、Referrer-Policy;需按场景条件化设置并绕过CDN验证。

Apache配置中设置安全响应头的正确位置
全局安全响应头必须写在主配置文件(httpd.conf)或启用的全局模块配置(如 security-headers.conf)中,且需位于 外部;若只写在某个 内,它只对该站点生效,无法实现“全局”覆盖。
常见错误是把 Header set 指令放在 .htaccess 里——这不仅性能差,还依赖 AllowOverride All,且无法控制 HTTPS 重定向前的响应头(比如 HSTS 必须在首次响应即生效)。
- 推荐做法:在
httpd.conf底部或/etc/httpd/conf.d/下新建security-headers.conf,用Include加载 - 确保
mod_headers已启用:a2enmod headers(Debian/Ubuntu)或检查LoadModule headers_module modules/mod_headers.so - 若使用 Apache 2.4+,优先用
Header always set而非Header set,避免被后置逻辑覆盖
必须设置的 5 个关键安全响应头及其取值逻辑
不是所有“推荐头”都适合直接全局开启。例如 Content-Security-Policy 若未精细适配资源路径,会导致页面白屏;而 Strict-Transport-Security 错误配置可能让站点在数月内无法通过 HTTP 访问。
-
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload—— 仅对已部署有效 HTTPS 的域名启用,且首次响应必须走 HTTPS;preload需手动提交至浏览器 HSTS Preload List -
X-Frame-Options: DENY—— 简单有效,但已被Content-Security-Policy: frame-ancestors 'none'取代;两者共存时后者优先 -
X-Content-Type-Options: nosniff—— 安全且无兼容性风险,强制浏览器不尝试 MIME 类型嗅探 -
X-XSS-Protection: 0—— 显式关闭旧版 IE/Chrome XSS Filter,避免触发误拦截导致页面渲染异常 -
Referrer-Policy: strict-origin-when-cross-origin—— 平衡隐私与功能,在跨域请求中只发送源站协议+主机名,不泄露路径
Apache中处理条件化响应头的典型场景
某些头需要按请求路径、协议或 MIME 类型动态开关,硬编码全局值会出问题。比如 API 接口可能需要放宽 CSP,而静态资源应禁用 script-src;又比如仅对 HTML 响应加 X-Frame-Options,PDF 则不该加。
Apache 提供 和 实现细粒度控制:
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'" env=REDIRECT_is_api
<if m>
Header always set X-Content-Type-Options "nosniff"
</if><filesmatch>
Header unset X-Frame-Options
</filesmatch>
注意:env=REDIRECT_is_api 需配合 RewriteRule 设置环境变量,否则无效; 在 Apache 2.4.10+ 才可用,低版本只能靠 + SetEnvIf 曲线救国。
验证与调试时最容易忽略的三个点
配置 reload 后看到 curl -I https://yoursite.com 返回了头,不代表它真的生效了——浏览器可能缓存了旧策略(尤其是 HSTS),或者 CDN 中间层覆盖了响应头。
- 用
curl -I -k https://yoursite.com --resolve 'yoursite.com:443:127.0.0.1'绕过 DNS 和 CDN,直连 Apache 验证原始响应 - 检查是否被 PHP 或应用框架二次输出头:PHP 的
header()函数、Django 的SECURE_HSTS_SECONDS都可能覆盖 Apache 设置 - HSTS 和 CSP 的语法错误会导致整个头被浏览器静默丢弃——用 Google CSP Evaluator 或浏览器 DevTools 的 Security 标签页确认解析结果
真正难的不是写那几行 Header 指令,而是厘清谁在什么时候、以什么顺序往响应里塞头;一旦中间有层(CDN、反向代理、WAF、应用代码)插手,全局配置就形同虚设。










