安全 HTTP 响应头

本文档的这部分讨论了安全 HTTP 响应头的一般主题。有关基于 Servlet基于 WebFlux 的应用中安全 HTTP 响应头的具体信息,请参见相关章节。

您可以通过多种方式使用 HTTP 响应头来增强 Web 应用的安全性。本节专门介绍 Spring Security 明确支持的各种 HTTP 响应头。如果需要,您还可以配置 Spring Security 来提供自定义头

默认安全头

有关如何为基于 Servlet基于 WebFlux 的应用自定义默认配置,请参见相关章节。

Spring Security 提供了一组默认的安全相关 HTTP 响应头,以提供安全的默认配置。

Spring Security 默认包含以下头

默认安全 HTTP 响应头
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 0

Strict-Transport-Security 仅在 HTTPS 请求中添加

如果默认设置不符合您的需求,您可以轻松地从这些默认设置中移除、修改或添加头。有关每个头的更多详细信息,请参见相应章节

缓存控制

有关如何为基于 Servlet基于 WebFlux 的应用自定义默认配置,请参见相关章节。

Spring Security 默认禁用缓存以保护用户内容。

如果用户认证后查看敏感信息然后注销,我们不希望恶意用户能够点击返回按钮查看敏感信息。默认发送的缓存控制头包括

默认缓存控制 HTTP 响应头
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0

为实现默认安全,Spring Security 默认添加这些头。但是,如果您的应用提供了自己的缓存控制头,Spring Security 会让出控制权。这使得应用能够确保静态资源(如 CSS 和 JavaScript)可以被缓存。

内容类型选项

有关如何为基于 Servlet基于 WebFlux 的应用自定义默认配置,请参阅相关章节。

从历史上看,包括 Internet Explorer 在内的浏览器会尝试通过内容嗅探来猜测请求的内容类型。这使得浏览器可以通过猜测未指定内容类型的资源的内容类型来改善用户体验。例如,如果浏览器遇到一个未指定内容类型的 JavaScript 文件,它就能猜测出内容类型然后运行它。

允许上传内容时,还有许多其他应该采取的措施(例如,仅在不同域中显示文档、确保设置 Content-Type 头、清理文档等)。但是,这些措施超出了 Spring Security 的提供范围。同样重要的是要指出,禁用内容嗅探时,您必须指定内容类型,以确保一切正常工作。

内容嗅探的问题在于它允许恶意用户使用 polyglots(即,一个文件同时满足多种内容类型的有效性)来执行 XSS 攻击。例如,某些网站可能允许用户提交有效的 Postscript 文档并查看它。恶意用户可能创建一个既是 Postscript 文档又是有效 JavaScript 文件的 polyglot,并用它进行 XSS 攻击。

默认情况下,Spring Security 通过向 HTTP 响应添加以下头来禁用内容嗅探

nosniff HTTP 响应头
X-Content-Type-Options: nosniff

HTTP Strict Transport Security (HSTS)

有关如何为基于 Servlet基于 WebFlux 的应用自定义默认配置,请参阅相关章节。

当您输入银行网站时,您输入的是 mybank.example.com 还是 https://mybank.example.com?如果您省略了 https 协议,您可能会受到中间人攻击 (Man-in-the-Middle attacks)。即使网站会重定向到 https://mybank.example.com,恶意用户也可能拦截最初的 HTTP 请求并操纵响应(例如,重定向到 https://mibank.example.com 并窃取其凭据)。

许多用户省略了 https 协议,这就是创建HTTP Strict Transport Security (HSTS) 的原因。一旦 mybank.example.com 被添加为 HSTS 主机,浏览器就能提前知道任何发送到 mybank.example.com 的请求都应该被解释为 https://mybank.example.com。这大大降低了发生中间人攻击的可能性。

根据RFC6797,HSTS 头仅注入到 HTTPS 响应中。为了让浏览器识别该头,浏览器必须首先信任用于建立连接的 SSL 证书的 CA(而不仅仅是 SSL 证书)。

将网站标记为 HSTS 主机的一种方式是将主机预加载到浏览器中。另一种方式是向响应中添加 Strict-Transport-Security 头。例如,Spring Security 的默认行为是添加以下头,该头指示浏览器将该域视为 HSTS 主机一年(非闰年有 31536000 秒)

Strict Transport Security HTTP 响应头
Strict-Transport-Security: max-age=31536000 ; includeSubDomains ; preload

可选的 includeSubDomains 指令指示浏览器也应将子域(例如 secure.mybank.example.com)视为 HSTS 域。

可选的 preload 指令指示浏览器应将该域预加载为 HSTS 域。有关 HSTS 预加载的更多详细信息,请参见 hstspreload.org

HTTP 公钥锁定 (HPKP)

为了保持被动,Spring Security 仍然提供在 Servlet 环境中对 HPKP 的支持。但是,由于前面列出的原因,Spring Security 团队不再推荐使用 HPKP。

HTTP 公钥锁定 (HPKP) 向 Web 客户端指定使用某个 Web 服务器时应使用哪个公钥,以防止伪造证书的中间人 (MITM) 攻击。如果正确使用,HPKP 可以为防御受损证书增加额外的保护层。然而,由于 HPKP 的复杂性,许多专家不再推荐使用它,甚至Chrome 也已经取消了对其的支持

有关不再推荐 HPKP 的更多详细信息,请阅读HTTP 公钥锁定已死? 以及我放弃使用 HPKP

X-Frame-Options

有关如何为基于 Servlet基于 WebFlux 的应用自定义默认配置,请参见相关章节。

允许您的网站被添加到框架中可能会带来安全问题。例如,通过巧妙的 CSS 样式,用户可能会被欺骗点击并非他们本意的内容。例如,登录银行的用户可能会点击一个授予其他用户访问权限的按钮。这种攻击被称为点击劫持 (Clickjacking)

处理点击劫持的另一种现代方法是使用内容安全策略 (CSP)

有多种方法可以缓解点击劫持攻击。例如,为了保护旧版浏览器免受点击劫持攻击,您可以使用框架破坏代码。虽然不完美,但框架破坏代码是您能为旧版浏览器做的最好的事情。

解决点击劫持的一种更现代的方法是使用X-Frame-Options 头。默认情况下,Spring Security 通过使用以下头来禁用在 iframe 中渲染页面

X-Frame-Options: DENY

X-XSS-Protection

有关如何为基于 Servlet基于 WebFlux 的应用自定义默认配置,请参见相关章节。

一些浏览器内置了过滤反射型 XSS 攻击的支持。该过滤器在主要浏览器中已被弃用,当前的 OWASP 建议是明确将该头设置为 0。

默认情况下,Spring Security 通过使用以下头来阻止内容

X-XSS-Protection: 0

内容安全策略 (CSP)

有关如何为基于 Servlet基于 WebFlux 的应用配置,请参见相关章节。

内容安全策略 (CSP) 是一种机制,Web 应用可以使用它来缓解内容注入漏洞,例如跨站脚本 (XSS)。CSP 是一种声明性策略,为 Web 应用作者提供了一种设施,用于声明并最终通知客户端(用户代理)Web 应用预期从哪些来源加载资源。

内容安全策略并非旨在解决所有内容注入漏洞。相反,您可以使用 CSP 来帮助减少内容注入攻击造成的损害。作为第一道防线,Web 应用作者应该验证其输入并对输出进行编码。

Web 应用可以通过在响应中包含以下 HTTP 头之一来使用 CSP

  • Content-Security-Policy

  • Content-Security-Policy-Report-Only

每个头都用作向客户端传递安全策略的机制。安全策略包含一组安全策略指令,每个指令负责声明特定资源表示的限制。

例如,Web 应用可以通过在响应中包含以下头来声明它预期从特定的受信任来源加载脚本

内容安全策略示例
Content-Security-Policy: script-src https://trustedscripts.example.com

用户代理会阻止尝试从 script-src 指令中声明的来源以外的任何其他来源加载脚本。此外,如果在安全策略中声明了report-uri 指令,用户代理会将违规行为报告给声明的 URL。

例如,如果 Web 应用违反了声明的安全策略,以下响应头指示用户代理将违规报告发送到策略的 report-uri 指令中指定的 URL。

带 report-uri 的内容安全策略
Content-Security-Policy: script-src https://trustedscripts.example.com; report-uri /csp-report-endpoint/

违规报告是标准的 JSON 结构,可以通过 Web 应用自己的 API 或公共托管的 CSP 违规报告服务(例如report-uri.io/)捕获。

Content-Security-Policy-Report-Only 头为 Web 应用作者和管理员提供了监视安全策略而不是强制执行策略的能力。此头通常在为网站试验或开发安全策略时使用。当策略被认为有效时,可以使用 Content-Security-Policy 头字段来强制执行它。

考虑以下响应头,该策略声明脚本可以从两个可能的来源之一加载。

仅报告内容安全策略
Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.example.com; report-uri /csp-report-endpoint/

如果网站违反此策略,尝试从 evil.example.com 加载脚本,用户代理会将违规报告发送到 report-uri 指令指定的声明 URL,但仍允许加载违规资源。

将内容安全策略应用于 Web 应用通常是一项非易事的任务。以下资源可能有助于为您的网站制定有效的安全策略

Referrer Policy

有关如何为基于 Servlet基于 WebFlux 的应用配置,请参见相关章节。

Referrer Policy 是一种机制,Web 应用可以使用它来管理 referrer 字段,该字段包含用户上次所在的页面。

Spring Security 的方法是使用Referrer Policy 头,该头提供了不同的策略

Referrer Policy 示例
Referrer-Policy: same-origin

Referrer-Policy 响应头指示浏览器告知目的地用户之前所在的来源。

Feature Policy

有关如何为基于 Servlet基于 WebFlux 的应用配置,请参见相关章节。

Feature Policy 是一种机制,允许 Web 开发者选择性地启用、禁用和修改浏览器中某些 API 和 Web 特性的行为。

Feature Policy 示例
Feature-Policy: geolocation 'self'

使用 Feature Policy,开发者可以为浏览器选择启用一组“策略”,以便在整个网站中使用的特定特性上强制执行。这些策略限制了网站可以访问哪些 API 或修改某些特性的浏览器默认行为。

Permissions Policy

有关如何为基于 Servlet基于 WebFlux 的应用配置,请参见相关章节。

Permissions Policy 是一种机制,允许 Web 开发者选择性地启用、禁用和修改浏览器中某些 API 和 Web 特性的行为。

Permissions Policy 示例
Permissions-Policy: geolocation=(self)

使用 Permissions Policy,开发者可以为浏览器选择启用一组“策略”,以便在整个网站中使用的特定特性上强制执行。这些策略限制了网站可以访问哪些 API 或修改某些特性的浏览器默认行为。

Clear Site Data

有关如何为基于 Servlet基于 WebFlux 的应用配置,请参见相关章节。

Clear Site Data 是一种机制,当 HTTP 响应包含此头时,可以删除任何浏览器端数据(cookies、本地存储等)

Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"

这是注销时执行的一个不错的清理操作。

自定义头

有关如何为基于 Servlet 的应用进行配置,请参见相关章节。

Spring Security 提供了方便的机制,可以轻松地将更常见的安全头添加到您的应用中。此外,它还提供了启用添加自定义头的钩子。