HTTP 安全响应头检查

每个响应头的作用、你当前的实际配置,以及该补上的那一行。不打分。

如果你才刚开始,该从哪里入手

这些响应头的价值并不相等,部署时的风险也不相等。下面按「用最小的弄坏东西的概率换取最多保护」的顺序排列:

响应头能挡住弄坏东西的风险
Strict-Transport-Security首次访问时的 HTTPS 降级没有,前提是你已经是全站 HTTPS
X-Content-Type-Options对上传文件的 MIME 嗅探实际上没有
Referrer-Policy把 URL 泄露给第三方低——可能影响分析工具的归因
X-Frame-Options / frame-ancestors点击劫持低,除非有什么东西正当地嵌入了你
Permissions-Policy嵌入的框架去索要摄像头或位置权限
Content-Security-Policy被注入的脚本执行高。 先用仅报告模式。

最后那一行是最要紧的一行,也是真正需要动手干活的一行。它上面的一切,一个下午就够了。

HSTS,以及它里面那个不可逆的决定

Strict-Transport-Security 告诉浏览器:在接下来的 max-age 秒里,对这个主机一律用 HTTPS,无论如何。它堵上了一个狭窄但真实的缺口:一位访客敲下 example.com,在你的跳转生效之前会先发出一个明文请求,而那个请求是可以被截获的。

Strict-Transport-Security: max-age=31536000; includeSubDomains

includeSubDomains 比它看上去更要紧。没有它,一个通过 HTTP 提供服务的子域名,仍然可以为父域名设置 cookie。有了它,每一个子域名都必须是全 HTTPS,否则就变得不可达——所以加之前先检查一遍。

preload 指令才是那个要好好想想的决定。它会让你的域名被烧进浏览器随版本发布的预加载列表里,于是在第一个请求发生之前,HTTPS 就已经被强制了。它同时也基本上是不可逆的:想要移除,得向列表维护者提出申请,然后等待浏览器版本一路发布出去,那是好几个月。等你确信无疑之后,它非常出色;但随手就加上,是件坏事。

CSP:仅报告模式不是可选项

内容安全策略是这里唯一能阻止被注入的脚本运行的响应头,也是唯一能把你的站点弄下线的那一个。这两个事实来自同一个性质:它限制了什么东西可以被加载。

带上一个收集端点,以仅报告模式部署它,让它在真实流量里跑上几周。你会发现的东西,和你读代码所预期的并不一样——会有一个你忘掉的字体主机,一个支付用的 iframe,还经常有一个在 CDN 边缘被注入的脚本,它在任何源文件里都找不到。最后那一类,正是仅报告模式存在的意义所在。

Content-Security-Policy-Report-Only: default-src 'self';
  script-src 'self'; object-src 'none'; base-uri 'self';
  report-uri /csp-report

有两样东西会抵消掉大部分收益。script-src 里的 'unsafe-inline' 恰恰允许了这条策略当初就是为了阻止的那种被注入的内联脚本——出路是 nonce 或哈希。而 'unsafe-eval' 会重新启用 eval 及其亲戚,某些较老的框架构建版本仍然需要它。本检查器会把这两者标记为「削弱」而不是「缺失」,因为带着它们的策略仍然在做有用的工作;只是它没有在做那件最主要的工作。

那些建议已经过期的响应头

  • `X-XSS-Protection`——它控制的浏览器过滤器已经从所有主流浏览器里被移除,而它当年本身就可以被操纵去弄坏页面。在 2026 年,这不是一个该设置的响应头。
  • `Expect-CT`——已废弃。证书透明度现在是无条件强制执行的,所以这个响应头什么也不做。
  • `Feature-Policy`——已改名为 Permissions-Policy,语法也不同。只有新名字会被认可。
  • `Public-Key-Pins`——已从浏览器中移除,而且移除得对。它里面一个失误,就能把你的域名在整个固定期内彻底锁死,且无从挽回。

本工具不检查什么

一个页面,一次响应。它会跟完跳转,读取最终那次响应上的响应头,然后就到此为止。它不会爬取站点,不会执行 JavaScript,不会测试你的 TLS 配置,也不会检查 cookie 的各项标志——而同一个站点上不同的路径,完全可能发送截然不同的响应头,所以检查首页告诉你的只是首页的情况。

专门针对 TLS 配置,Qualys SSL Labs 是那件成名已久的工具,而且很彻底。至于证书本身,这一个会读出一台主机实际出示的是什么。

响应头相关问题

为什么没有评分或等级?

因为等级恰恰是唯一让人无从下手的输出。知道自己得了个 C,并不能告诉你缺的是哪个响应头、它对你的站点为什么要紧、该设成什么——而且它会诱使人为了把字母往上提而加响应头,而不是为了解决问题。一个有严格 CSP 却没有 Permissions-Policy 的站点,状况远好过一个设了六个响应头但值都很宽松的站点,而没有哪一个字母能表达这一点。所以这里逐项报告每个响应头,评判你实际发出的那个值,并直接给你可以粘上去的那一行。

我该先加哪个响应头?

如果你已经是全站 HTTPS,就先加 Strict-Transport-Security。它只有一行,不会弄坏任何本来正常的东西,还能关上首次访问时的降级窗口。接着是仅报告模式的 Content-Security-Policy——那才是真正有牙齿的一个,而仅报告模式让你在真正开始强制之前,先弄清楚你的站点实际加载了些什么。X-Content-Type-Options: nosniff 同样不花什么代价,本来就该开着。

内容安全策略会不会把我的站点弄坏?

很容易弄坏,正因如此才有仅报告模式。先部署带收集端点的 Content-Security-Policy-Report-Only,让它在真实流量里跑上两三周,然后读它报上来的内容——你会发现一些自己早就忘了的资源,还经常会发现 CDN 或分析服务在边缘注入的、任何源文件里都找不到的东西。等到报告安静下来,再切换到强制模式。仅凭读一遍代码库就写出策略并直接强制,正是结账页面挂掉的经典剧本。

X-XSS-Protection 值得设置吗?

不值得。它控制的是一个浏览器 XSS 过滤器,而这个过滤器已经从所有主流浏览器里移除了——Chrome 在 2019 年就去掉了——而且它当年本身就引入过漏洞,因为它可以被操纵,去弄坏那些本来并不存在漏洞的页面。如果某个扫描器非要它不可,把它设成 0 还说得过去;设成 1; mode=block 则是在重复一条多年前就已失效的建议。它的替代品是 Content-Security-Policy。

有了 CSP,还需要 X-Frame-Options 吗?

不需要,前提是你的 CSP 设置了 frame-ancestors,在所有当前浏览器里它都取代了前者。本检查器认得这一点,当 frame-ancestors 已经在履职时,不会把 X-Frame-Options 报成缺失。两个都留着也不花什么代价,但只在老到那种程度的浏览器上才有帮助,而你那时多半有更大的麻烦要操心。

缺少某个响应头,就意味着我有漏洞吗?

不意味着。安全响应头属于纵深防御——它们限制一个漏洞造成的损害,而不会制造或消除漏洞本身。没有 CSP 的站点并不因此就有 XSS 漏洞;有 XSS 缺陷的站点才有,而 CSP 的作用是阻止那个缺陷演变成彻底沦陷。添加响应头既值得又便宜,但它替代不了输出编码、输入校验和把依赖保持在最新。

最后审校于 。发现有内容过时了? 告诉我们.