免费 · 无需账户

HTTP 安全响应头检测工具

在线检查公开网站的 HTTP 安全响应头。输入一个域名,查看八个关键安全响应头在最终响应中的评估结果,以及可显示时观察到的值。

免费检查网站的公开设置,不会更改您的网站。

无需注册 无破坏性流量 公开网站检查
响应头参考

每个响应头的作用及评估方式

此工具在一个响应中读取这些响应头。大多数行是存在性检查:只要发送了该响应头就计入,并在可用时显示其值,方便你判断它是否适合你的网站。

响应头作用良好配置此工具的评估方式
Strict-Transport-Security让再次访问的浏览器在发出任何明文 HTTP 请求之前,自动切换到 HTTPS。逐步上线完成后使用较长的 max-age(180 天或更长);各阶段见指南。HTTPS 目标缺少此头:中。输入 http:// 地址时不评估。
Content-Security-Policy为浏览器提供页面代码和内容允许使用的来源清单。根据页面实际使用的资源制定的策略,不含宽泛的脚本例外。缺失:中。会显示其值,但不审查内容。
X-Frame-Options · frame-ancestors阻止其他网站在自己的框架中显示你的页面。在 CSP 中使用 frame-ancestors,并以 X-Frame-Options 作为旧浏览器的后备。两者都没有:中。
X-Content-Type-Options让浏览器信任每个响应声明的内容类型。唯一的值 nosniff。缺失或为其他任何值:低。
Referrer-Policy限制访客点击你的链接时,其他网站能看到你的页面地址的哪一部分。至少与当前浏览器默认值同样严格的策略。缺失:低。
Access-Control-Allow-Origin决定哪些其他网站的脚本可以读取你的响应。普通页面不发送,或只指定一个可信的 origin。通配符(*):中。
Server · X-Powered-By公开响应背后的软件。删除,或改为通用值。存在任何 Server 或 X-Powered-By 头:低,即使没有版本号。只显示识别出的技术名称。
Set-Cookie设置 Cookie;其属性决定哪些脚本可以读取它们以及何时发送。会话 Cookie 对脚本隐藏,并且只通过 HTTPS 发送。此响应中的 Cookie 缺少 HttpOnly,或在 HTTPS 下缺少 Secure:中。不检查 SameSite,也从不显示 Cookie 值。

Permissions-Policy 和 Cross-Origin-Opener-Policy 不在此页面评估。上线准备 Snapshot 只在单独的加固等级中计入它们。

如何修复

如何在服务器上添加这些响应头

每个响应头只在一个响应所有请求的层级中设置,例如 Web 服务器、CDN 或托管平台。先使用下面的值,然后在测试关键页面的同时逐步收紧。

安全的初始值

  1. 01Strict-Transport-Security: max-age=300只在 HTTPS 响应中发送;浏览器会忽略通过未加密 HTTP 收到的该响应头。分阶段提高 max-age,例如先到一周、再到一个月、然后到一年(31536000),每一步都检查网站。只有当所有子域名都提供 HTTPS 时才添加 includeSubDomains;只有在阅读 hstspreload.org 的要求之后才添加 preload,因为退出预加载列表需要数月。
  2. 02Content-Security-Policy-Report-Only: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'Report-Only 不会拦截任何内容:浏览器只会在控制台中报告策略将拦截的内容,如果你添加了报告端点,也会发送到那里。打开关键页面,加入它们实际使用的来源,然后把同一策略作为 Content-Security-Policy 发送。脚本应避免 'unsafe-inline';nonce 或哈希是更严格的选择。
  3. 03frame-ancestors 'self' · X-Frame-Options: SAMEORIGIN已生效的 Content-Security-Policy 中的 frame-ancestors 决定哪些网站可以在框架中显示你的页面。X-Frame-Options 覆盖旧浏览器,并在 CSP 仍处于 Report-Only 时负责拦截。如果页面从不被嵌入,请使用 'none' 和 DENY,并让两个值保持一致。frame-ancestors 要作为响应头发送,因为浏览器会忽略 meta 标签中的该指令。
  4. 04X-Content-Type-Options: nosniff在每个响应中发送唯一的值 nosniff。之后浏览器会拒绝以错误 Content-Type 提供的脚本和样式表,所以请先确认服务器为 JavaScript 和 CSS 文件设置了正确的类型。
  5. 05Referrer-Policy: strict-origin-when-cross-origin其他网站只会收到你的源(origin),不会收到完整的页面地址;当链接从 HTTPS 指向 HTTP 时则什么都不发送。当前浏览器已将其作为默认值;显式发送可让所有浏览器的行为一致。如果 URL 中含有私密数据,请选择 same-origin 或 no-referrer。
  6. 06Permissions-Policy: camera=(), microphone=(), geolocation=()空列表 () 会为你的页面及其嵌入的每个框架关闭某项功能。只列出网站从不使用的功能,然后测试包含地图、视频通话或支付组件的页面。

按平台分类的可复制示例

每个示例都设置相同的初始值。托管平台可能已经发送 Strict-Transport-Security,因此 Vercel、Netlify 和 Next.js 示例中没有包含它;请检查实际响应,只在缺少时添加。

nginx

把这些行放在提供 HTTPS 的 server 块中。always 参数会让它们也出现在错误响应中。带有自己 add_header 行的 location 块会丢弃从 server 块继承的所有 add_header,所以要在那里重复整组设置,或把它们放在一个 include 文件中。

# In the server block that serves HTTPS (listen 443 ssl)
add_header Strict-Transport-Security "max-age=300" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Apache

启用 mod_headers,并把这些行添加到 443 端口的虚拟主机中,或添加到已设置 AllowOverride FileInfo 的 .htaccess 中。Header always set 同样适用于错误响应和重定向。

# <VirtualHost *:443> or .htaccess; needs mod_headers (Debian/Ubuntu: a2enmod headers)
Header always set Strict-Transport-Security "max-age=300"
Header always set Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"

Cloudflare

在控制台中为你的主机名创建一条 Response Header Transform Rule,并用 Set static 操作添加每个响应头;该操作会替换源站发送的同名响应头。HSTS 在 SSL/TLS 的 Edge Certificates 下有单独的设置;二者只用其一。菜单名称可能因控制台版本而不同。

Rule type   Response Header Transform Rule
When        Hostname equals example.com
Then        Set static, one row per header:
  X-Content-Type-Options               nosniff
  Referrer-Policy                      strict-origin-when-cross-origin
  X-Frame-Options                      SAMEORIGIN
  Permissions-Policy                   camera=(), microphone=(), geolocation=()
  Content-Security-Policy-Report-Only  default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'

HSTS        SSL/TLS > Edge Certificates > HTTP Strict Transport Security (HSTS)

Vercel

在项目根目录的 vercel.json 中添加 headers 条目。source 模式 /(.*) 匹配所有路径;如果某些路由需要不同的策略,请缩小范围。

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Content-Security-Policy-Report-Only", "value": "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" },
        { "key": "X-Frame-Options", "value": "SAMEORIGIN" },
        { "key": "X-Content-Type-Options", "value": "nosniff" },
        { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
        { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
      ]
    }
  ]
}

Netlify

在发布目录(即 Netlify 部署的文件夹)中创建名为 _headers 的文件。每个路径行(如 /*)后面跟着缩进的“名称: 值”行。同样的规则也可以写在 netlify.toml 的 [[headers]] 下。

/*
  Content-Security-Policy-Report-Only: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()

Next.js

在 next.config.js 的 async headers() 函数中返回这些响应头;source '/:path*' 覆盖所有路由。静态导出(output: 'export')时 headers() 不会运行,此时请在提供导出文件的主机上设置响应头。

// next.config.js
const securityHeaders = [
  { key: 'Content-Security-Policy-Report-Only', value: "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" },
  { key: 'X-Frame-Options', value: 'SAMEORIGIN' },
  { key: 'X-Content-Type-Options', value: 'nosniff' },
  { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
  { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
];

module.exports = {
  async headers() {
    return [{ source: '/:path*', headers: securityHeaders }];
  },
};

部署后再次运行此工具:它读取最终响应,因此会显示 CDN 或平台实际发送的内容。然后在浏览器开发者工具中打开一个错误页面和一个静态文件,因为响应头经常只为部分响应设置。

解读结果

如何理解每种状态。

  1. 01通过找到了该响应头,并通过存在性检查。
  2. 02低 · 中 · 高某项缺失,或其设置方式被此检查标记。级别与完整 Snapshot 使用的相同。
  3. 03已观察记录了一个值,但检查既未判定通过,也未产生发现。
  4. 04未观察到检查已运行,但没有可记录的内容,例如响应中没有 Cookie。
  5. 05不适用该检查不适用,例如输入 http:// 地址时的 HSTS。
  6. 06未测量未收到可用的响应,因此该检查不计为通过。
范围

此工具不做的事。

  1. 01只请求你输入的 origin 的首页。会丢弃 path 和 query,不请求其他页面。
  2. 02主要检查响应头是否存在,而不是其值是否适合你的网站。
  3. 03只有在你输入 http:// 地址时才测试 HTTP 到 HTTPS 的重定向;那次运行会跳过 TLS,也不会报告缺少 HSTS。
  4. 04它不是漏洞扫描或渗透测试,也不发送攻击流量。
  5. 05结果是某个响应在某一时刻的状态;CDN 规则或其他页面可能发送不同的响应头。
常见问题

关于响应头检查的问题。

为什么没有版本号的 Server: nginx 也会被标记?

任何 Server 或 X-Powered-By 头都评为低,因为仅名称就会告诉访客网站运行的是什么软件。如果平台允许,请删除该头或改为通用值。

为什么结果与我的服务器配置不同?

此工具读取最多五次重定向后收到的响应。起作用的是 CDN、代理或托管平台添加或删除后的响应头;CDN、代理或机器人防护规则对浏览器的响应也可能与对此工具的不同。

我可以检查不属于我的网站吗?

可以。响应头检查读取的是网站本来就发送给每位访客的一个普通响应;完整运行还会为其他检查再发送几次普通请求。受保护模块和完整审计需要已验证目标或明确授权。

这是漏洞扫描吗?

不是。这是对响应头的被动检查,不是漏洞扫描或渗透测试,也不能证明网站是安全的。

为什么有些响应中缺少我的响应头?

响应头经常只为某个路由、文件类型或状态码设置。在 nginx 中,不带 always 的 add_header 会跳过错误响应,而带有自己 add_header 行的 location 块会丢弃 server 块中的设置。静态文件、API 路由以及由其他服务提供的页面也可能绕过添加响应头的规则。

可以在应用和 CDN 中同时设置同一个响应头吗?

每个响应头只在一个层级中设置。如果两个层级都添加,浏览器可能收到两个值:对于 Content-Security-Policy,发送的每个策略都会生效,结果比任何一个都更严格;对于 Strict-Transport-Security,只使用第一个响应头。

我应该把域名提交到 HSTS 预加载列表吗?

只有当现在和将来的所有子域名都能提供 HTTPS 时才应提交。该列表要求 max-age 至少一年,并带有 includeSubDomains 和 preload;之后浏览器在首次访问之前就会对该域名使用 HTTPS,而从列表中移除可能需要数月才能到达用户。即使不使用 preload,较长的 max-age 也已覆盖回访用户。

下一步

将检测到的问题转化为清晰的修复计划。