安全 HTTP 响应头
默认安全标头
Spring Security 提供了一组默认的安全相关HTTP响应头,以提供安全默认配置。
Spring Security 的默认设置包含以下响应头:
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 请求添加
如果默认设置无法满足您的需求,您可以轻松地从这些默认值中移除、修改或添加标头。有关每个标头的更多详细信息,请参阅相应章节:
缓存控制
Spring Security 默认禁用缓存以保护用户内容。
如果用户通过身份验证查看敏感信息后退出登录,我们不希望恶意用户能够通过点击后退按钮来查看这些敏感信息。默认发送的缓存控制头包括:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
为了确保默认安全,Spring Security 默认会添加这些头部信息。然而,如果您的应用程序提供了自己的缓存控制头部,Spring Security 则会退出干预。这使得应用程序能够确保静态资源(如 CSS 和 JavaScript)可以被缓存。
内容类型选项
历史上,包括 Internet Explorer 在内的浏览器会尝试通过内容嗅探来猜测请求的内容类型。这使得浏览器能够通过猜测未指定内容类型的资源的内容类型来改善用户体验。例如,如果浏览器遇到一个未指定内容类型的 JavaScript 文件,它将能够猜测内容类型并运行该文件。
在允许上传内容时,还需要采取许多额外措施(例如仅在独立域中显示文档、确保设置 Content-Type 标头、对文档进行清理等)。然而,这些措施超出了 Spring Security 提供的功能范围。同样重要的是要指出,在禁用内容嗅探时,必须指定内容类型才能确保功能正常运行。
内容嗅探的问题在于,它允许恶意用户利用多态文件(即同时符合多种内容类型格式的文件)实施XSS攻击。例如,某些网站可能允许用户提交有效的PostScript文档并在线查看。恶意用户可能创建一个同时符合JavaScript格式的PostScript文档,并借此实施XSS攻击。
默认情况下,Spring Security 通过向 HTTP 响应添加以下标头来禁用内容嗅探:
X-Content-Type-Options: nosniff
HTTP 严格传输安全(HSTS)
当你输入银行网站时,是输入 mybank.example.com 还是 https://mybank.example.com?如果省略 https 协议,你可能会受到中间人攻击的威胁。即使网站执行了重定向到 https://mybank.example.com,恶意用户也可能拦截初始的 HTTP 请求并篡改响应(例如,重定向到 https://mibank.example.com 并窃取凭据)。
许多用户会省略 https 协议,这正是 HTTP 严格传输安全(HSTS) 被创建的原因。一旦 mybank.example.com 被添加为 HSTS 主机,浏览器就能提前知道,任何对 mybank.example.com 的请求都应被解释为 https://mybank.example.com。这大大降低了发生中间人攻击的可能性。
根据 RFC6797 的规定,HSTS 头部仅被注入到 HTTPS 响应中。为了让浏览器识别该头部,浏览器必须首先信任用于建立连接的 SSL 证书的签发 CA(而不仅仅是 SSL 证书本身)。
网站被标记为HSTS主机的一种方式是让浏览器预加载该主机。另一种方式是在响应中添加Strict-Transport-Security头部。例如,Spring Security 的默认行为是添加以下头部,该头部指示浏览器在一年内(非闰年有 31536000 秒)将该域名视为 HSTS 主机:
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) 向网络客户端指定与特定网络服务器一起使用的公钥,以防止使用伪造证书的中间人(MITM)攻击。如果使用得当,HPKP 可以增加额外的保护层,防止证书被泄露。然而,由于 HPKP 的复杂性,许多专家不再推荐使用它,Chrome 甚至已经移除了对它的支持。
关于为何不再推荐使用HPKP的更多详细信息,请阅读《HTTP公钥固定已死?》和《我放弃使用HPKP》。
X-Frame-Options
允许网站被嵌入框架可能存在安全隐患。例如,攻击者可通过巧妙的CSS样式设计,诱使用户点击非预期内容。假设用户已登录银行账户,可能误触授予他人访问权限的按钮。此类攻击被称为点击劫持。
另一种应对点击劫持的现代方法是使用内容安全策略(CSP)。
有多种方法可以缓解点击劫持攻击。例如,为了保护旧版浏览器免受点击劫持攻击,你可以使用框架破坏代码。虽然并非完美,但框架破坏代码是针对旧版浏览器的最佳解决方案。
一种更现代的解决点击劫持问题的方法是使用 X-Frame-Options 头部。默认情况下,Spring Security 通过设置以下头部来禁止在 iframe 中渲染页面:
X-Frame-Options: DENY
X-XSS-Protection
某些浏览器内置了过滤反射型XSS攻击的功能。该过滤器已在主流浏览器中被弃用,当前 OWASP 建议是将标头显式设置为 0。
默认情况下,Spring Security 通过以下响应头来阻止内容:
X-XSS-Protection: 0
内容安全策略 (CSP)
内容安全策略 (CSP) 是一种机制,Web 应用程序可以利用它来缓解内容注入漏洞,例如跨站脚本 (XSS)。CSP 是一种声明式策略,为 Web 应用程序作者提供了一种方式,用于声明并最终告知客户端(用户代理)Web 应用程序期望从哪些来源加载资源。
内容安全策略(CSP)并非旨在解决所有内容注入漏洞。相反,你可以使用 CSP 来帮助减轻内容注入攻击造成的危害。作为第一道防线,Web 应用开发者应当验证其输入并编码其输出。
Web应用程序可以通过在响应中包含以下HTTP头部之一来使用CSP:
Content-Security-PolicyContent-Security-Policy-Report-Only
这些头部信息均用作向客户端传递安全策略的机制。安全策略包含一组安全策略指令,每条指令负责声明特定资源表示形式的限制条件。
例如,一个Web应用程序可以通过在响应中包含以下头部来声明它期望从特定的、受信任的来源加载脚本:
Content-Security-Policy: script-src https://trustedscripts.example.com
尝试加载一个脚本,其来源与 script-src 指令中声明的来源不同,会被用户代理阻止。此外,如果在安全策略中声明了 report-uri 指令,用户代理会将违规行为报告给声明的 URL。
例如,如果某个Web应用违反了声明的安全策略,以下响应头会指示用户代理将违规报告发送到策略report-uri指令中指定的URL。
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
Referrer Policy 是一种机制,Web 应用程序可以通过它来管理 referrer 字段,该字段包含用户之前访问的最后一个页面。
Spring Security 采用的方法是使用 Referrer Policy 标头,该标头提供了多种不同的策略:
Referrer-Policy: same-origin
Referrer-Policy 响应头指示浏览器告知目标站点用户先前所在的来源。
功能策略
Feature Policy 是一种机制,允许 Web 开发者在浏览器中有选择地启用、禁用和修改某些 API 及 Web 功能的行为。
Feature-Policy: geolocation 'self'
借助功能策略,开发者可以选择启用一组“策略”,让浏览器在整个网站中强制执行特定功能的使用。这些策略会限制网站可访问的API,或修改浏览器对某些功能的默认行为。
权限策略
Permissions Policy 是一种机制,允许 Web 开发者有选择地在浏览器中启用、禁用和修改某些 API 及 Web 功能的行为。
Permissions-Policy: geolocation=(self)
借助Permissions Policy,开发者可以选择启用一组“策略”,让浏览器在整个网站使用的特定功能上强制执行。这些策略会限制网站可以访问的API,或修改浏览器对某些功能的默认行为。
清除网站数据
Clear Site Data 是一种机制,当 HTTP 响应包含此头部时,可以移除任何浏览器端的数据(如 Cookie、本地存储等):
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
这是一个在注销时执行的不错的清理操作。
自定义头部
请参阅相关章节了解如何配置基于 servlet 的应用程序。
Spring Security 提供了便捷的机制,可以将更常见的安全标头添加到您的应用程序中。同时,它也提供了钩子功能,支持添加自定义标头。