安全响应头详解
安全响应头是 HTTP 响应中的一行,它改变访客浏览器可以对你的页面做的事情:只从指定的来源运行脚本、再也不说明文 HTTP、拒绝被嵌入框架、拒绝猜测内容类型。它们都不需要代码、库或重启——然而大多数网站很少发送、甚至完全不发送它们,这就是为什么大多数网站在扫描器检查时得 F。本文逐个响应头说明每个到底拦截什么,解释 F 的流行,并给出以每小时工作量换取最多保护的修复顺序。想看自己网站的判定,先运行安全响应头深度检查,然后对照你的结果阅读。
响应头是给浏览器的指令,不是服务器的盔甲
先说响应头不是什么。安全响应头不修补你的应用,不过滤你的流量,也不认证任何人。它是服务器附在响应上的一个声明,而浏览器——访客的浏览器,在访客的机器上——从那一刻起执行它。这听起来很弱,直到你注意到有多少攻击是由浏览器替攻击者执行的:运行某人注入评论字段的脚本,把你的登录页加载到恶意网站上的一个不可见框架里,因为一个上传的文本文件内容看起来像脚本就把它当作 HTML 处理。响应头是服务器提前告诉浏览器的方式:这些动作在这个网站上从来都不合法。
它们也是纵深防御,应该这样理解。这个领域的权威参考是 MDN HTTP 文档,它规定了每个响应头的语法和语义,以及 OWASP Secure Headers Project——OWASP Web 安全测试指南中的测试指引正是指向它推荐的值。这两个来源都不承诺响应头能让网站安全。它们承诺的是更窄但真实的事情:设置好响应头后,即使应用漏洞给了攻击者一个立足点,整类由浏览器执行的攻击也会停止工作。
每个响应头到底拦截什么
Content-Security-Policy 阻止注入的脚本运行。XSS 及其近亲——携带脚本的存储型评论、通过被攻陷的第三方标签注入的盗刷脚本——都需要浏览器执行网站从未打算执行的代码。CSP 是一个允许列表:script-src 指明脚本可以来自哪些源,其余一切,包括内联脚本和从攻击者服务器加载的任何东西,都会被拒绝。它的弱形式很有名:包含 'unsafe-inline' 的策略让每个内联脚本都能运行,包括被注入的那个,这就是为什么检查器把这样的策略判为弱而不是好。CSP 是部署起来最重的响应头,也是拦截最多的一个。
Strict-Transport-Security 阻止降级。访客第一次输入你的域名而不带协议、或者跟随一个旧的 http:// 链接时,那个请求以明文穿过网络,在途中可以被剥离、重定向或读取——会话 Cookie 也在其中。HSTS 告诉浏览器:在接下来的 max-age 秒内,把这个主机的每个 http:// URL 在任何东西离开机器之前改写为 https://,并拒绝证书错误的点击穿透。一个诚实的局限:HSTS 只保护那些浏览器已经见过一次该响应头的访客(内置在浏览器中的预加载列表正是为了弥补这第一次访问的缺口),而且它只在自己通过 HTTPS 到达时才会被遵从。
框架防护阻止点击劫持。如果你的页面可以被嵌入框架,恶意网站可以把你真实的界面铺在它自己一层透明按钮之下,收割点击——受害者看到一个看起来无害的页面,却批准了一笔转账。CSP 指令 frame-ancestors(以及它的前辈 X-Frame-Options: DENY 或 SAMEORIGIN)指明谁可以把你放进框架;其他所有人得到的只是一个空白框架。X-Content-Type-Options: nosniff 阻止一个更安静的伎俩:浏览器历史上会二次猜测声明的 Content-Type,在内容看起来对路时把文件当作脚本或 HTML 执行,从而把一次无辜的上传变成存储型 XSS。nosniff 结束了猜测——声明的类型就是类型。
Referrer-Policy 阻止 URL 泄露。当访客从你的页面点击到另一个网站时,浏览器历史上会把你页面的完整 URL 作为 Referer 发送出去——包括其中坐着的任何密码重置令牌、搜索词或记录 ID。strict-origin-when-cross-origin 或更严格的策略跨站时只发送源,并且不向容易降级的 http 目标发送任何东西。Permissions-Policy 阻止功能滥用:它声明这个网站到底可以使用哪些强大的浏览器能力——摄像头、麦克风、地理位置、支付处理器——这样被注入的框架或脚本就无法以你的名义悄悄请求它们。而奖励响应头 Cross-Origin-Opener-Policy 切断你的页面与跨源弹窗之间的 window.opener 链接,把你的浏览上下文与可能探测它的页面隔离开来。
为什么这么多网站得 F
因为没有任何默认配置会发送这些响应头。一个原装的 Web 服务器、一个原装的框架脚手架、一个原装的静态托管:每个发出的响应最多带有六个中的一两个,而最有价值的两个——CSP 和 Permissions-Policy——需要针对具体网站做决定,因此没有任何默认配置能安全地附带它们。然后责任被分成三份:框架团队以为服务器会加响应头,服务器团队以为框架会加,而前面的 CDN 反正会按自己的意愿改写。响应头就这样悄无声息地从缝隙中掉下去,因为没有它们时表面上一切都不坏。一个得 F 的网站通常看起来和工作起来都和得 A 的一模一样;差别只在某一天某个攻击需要浏览器配合时显现。
公布的数字与这个故事吻合。2026-11-04 的每周工具扫描综述中报道的一个扫描器的公布样本发现:65% 的被扫描网站得 F,51% 完全没有发送 Content-Security-Policy。请把这些当作它们本来的样子——一个扫描器的样本、由第三方公布,不是整个网络的测量,也不是我们自己的数据——但方向与每个运维者的经验一致:响应头是那种缺失反而是统计常态的罕见安全控制。这也是这个统计中藏着的好消息:门槛低得在地板上,而爬上去靠的是配置,不是工程。
修复顺序:按每小时的影响
按安全响应头深度检查所显明的顺序工作。第一,一行搞定的:X-Content-Type-Options: nosniff、框架防护和一个合理的 Referrer-Policy——100 分中的 35 分、几分钟的工作量,在普通网站上实际上零破坏风险。第二,HSTS——再加 20 分——但只有在核实每个页面、子域名和遗留重定向都真的能通过 HTTPS 工作之后,因为长的 max-age 一旦发出就收不回来。第三,Permissions-Policy:列出你的网站真正使用的功能,关掉其余的;一行细心的配置换 10 分。
最后,而且慢慢来,CSP。它的 35 分是最大的单块,也是唯一能把你自己的网站搞垮的修复。先把它以 Content-Security-Policy-Report-Only 加报告端点的形式部署,读一周的违规报告,改写它标出的内联脚本和事件处理程序——或者按 MDN 指引采用 nonce——并只在报告安静下来后才切换为强制执行。只要你不依赖跨源弹窗流程,就顺手加上 Cross-Origin-Opener-Policy: same-origin;它在我们的表里不计分,但是便宜的隔离。然后重新运行检查,确认你在源站加的响应头真的穿过了它前面的 CDN 和代理。
响应头做不到什么
它们修不了漏洞,只能缩小攻击者通过漏洞能做的事情。CSP 不修复那个没有转义输入的评论字段;它让被注入的负载拒绝运行。HSTS 不修复损坏的证书链——那是 SSL 评分器的领域——没有任何响应头能替代打补丁、备份或访问控制。把一个完美的响应头等级理解为一栋楼上锁得很好的大门,而其他楼层仍然需要各自的检查,那正是 网站健康检查的用途。
它们也不能一劳永逸。为去年的网站写的 CSP 会悄悄地拦住今年的支付组件——或者更糟,在匆忙中被用 * 放宽,从此什么都不再意味着。像对待其余配置一样对待响应头集合:纳入版本管理、网站变化时评审、在每次平台迁移后重新检查。检查只要十秒钟;每当你页面前面的技术栈发生变化时就运行一次,F 的流行就仍然是别人的统计数字。