Security HTTP Response Headers
你可以使用 Security HTTP Response Headers 来提高 Web 应用程序的安全性。此部分专门讨论 Security HTTP 响应头的基于服务的支持。
You can use Security HTTP Response Headers to increase the security of web applications. This section is dedicated to servlet-based support for Security HTTP Response Headers.
Default Security Headers
Spring Security 提供一个 default set of Security HTTP Response Headers 来提供安全的默认值。虽然每个头都可认为是最佳实践,但应注意并非所有客户端都使用这些头,因此建议进行其他测试。
Spring Security provides a default set of Security HTTP Response Headers to provide secure defaults. While each of these headers are considered best practice, it should be noted that not all clients use the headers, so additional testing is encouraged.
你可以自定义特定标头。例如,假设你希望设置默认值,但希望为 X-Frame-Options 指定 SAMEORIGIN
。
You can customize specific headers.
For example, assume that you want the defaults but you wish to specify SAMEORIGIN
for servlet-headers-frame-options.
你可以使用以下配置来实现:
You can do so with the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.sameOrigin()
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<frame-options policy="SAMEORIGIN" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
frameOptions {
sameOrigin = true
}
}
}
return http.build()
}
}
如果你不希望添加默认值并希望明确控制应该使用什么,你可以禁用默认值。以下代码清单展示了如何执行此操作。
If you do not want the defaults to be added and want explicit control over what should be used, you can disable the defaults. The next code listing shows how to do so.
如果你使用 Spring Security 的配置,以下仅会添加 Cache Control :
If you use Spring Security’s configuration, the following adds only Cache Control:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
// do not use any default headers unless explicitly listed
.defaultsDisabled()
.cacheControl(withDefaults())
);
return http.build();
}
}
<http>
<!-- ... -->
<headers defaults-disabled="true">
<cache-control/>
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
// do not use any default headers unless explicitly listed
defaultsDisabled = true
cacheControl {
}
}
}
return http.build()
}
}
如有必要,你可以使用以下配置禁用所有 HTTP 安全性响应头:
If necessary, you can disable all of the HTTP Security response headers with the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers.disable());
return http.build();
}
}
<http>
<!-- ... -->
<headers disabled="true" />
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
disable()
}
}
return http.build()
}
}
Cache Control
Spring Security 默认包含 Cache Control 头。
Spring Security includes Cache Control headers by default.
但是,如果你实际上想缓存特定响应,你的应用程序可以选择性地调用 link:https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html#setHeader(java.lang.String,java.lang.String)[HttpServletResponse.setHeader(String,String)
来覆盖 Spring Security 设置的头。你可以使用此操作来确保内容(例如 CSS、JavaScript 和图像)得到正常缓存。
However, if you actually want to cache specific responses, your application can selectively invoke HttpServletResponse.setHeader(String,String)
to override the header set by Spring Security.
You can use this to ensure that content (such as CSS, JavaScript, and images) is properly cached.
当您使用 Spring Web MVC 时,这通常在您的配置中完成。您可以在 Spring 参考文档的 Static Resources 部分中找到如何执行此操作的详细信息。
When you use Spring Web MVC, this is typically done within your configuration. You can find details on how to do this in the Static Resources portion of the Spring Reference documentation
如有必要,你还可以禁用 Spring Security 的缓存控制 HTTP 响应头。
If necessary, you can also disable Spring Security’s cache control HTTP response headers.
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.cacheControl(cache -> cache.disable())
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<cache-control disabled="true"/>
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
cacheControl {
disable()
}
}
}
return http.build()
}
}
Content Type Options
Spring Security 默认包含 Content-Type 头。但是,你可以禁用它:
Spring Security includes Content-Type headers by default. However, you can disable it:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<content-type-options disabled="true"/>
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
contentTypeOptions {
disable()
}
}
}
return http.build()
}
}
HTTP Strict Transport Security (HSTS)
默认情况下,Spring Security 提供 Strict Transport Security 头。然而,你可以明确自定义结果。以下示例明确提供了 HSTS:
By default, Spring Security provides the Strict Transport Security header. However, you can explicitly customize the results. The following example explicitly provides HSTS:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.preload(true)
.maxAgeInSeconds(31536000)
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<hsts
include-subdomains="true"
max-age-seconds="31536000"
preload="true" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
httpStrictTransportSecurity {
includeSubDomains = true
preload = true
maxAgeInSeconds = 31536000
}
}
}
return http.build()
}
}
HTTP Public Key Pinning (HPKP)
Spring Security 提供 HTTP Public Key Pinning 的服务支持,但它是 no longer recommended 。
Spring Security provides servlet support for HTTP Public Key Pinning, but it is no longer recommended.
你可以使用以下配置启用 HPKP 头:
You can enable HPKP headers with the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.httpPublicKeyPinning(hpkp -> hpkp
.includeSubDomains(true)
.reportUri("https://example.net/pkp-report")
.addSha256Pins("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=", "E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=")
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<hpkp
include-subdomains="true"
report-uri="https://example.net/pkp-report">
<pins>
<pin algorithm="sha256">d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=</pin>
<pin algorithm="sha256">E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=</pin>
</pins>
</hpkp>
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
httpPublicKeyPinning {
includeSubDomains = true
reportUri = "https://example.net/pkp-report"
pins = mapOf("d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=" to "sha256",
"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" to "sha256")
}
}
}
return http.build()
}
}
X-Frame-Options
默认情况下,Spring Security 指示浏览器使用 X-Frame-Options 阻止反射 XSS 攻击。
By default, Spring Security instructs browsers to block reflected XSS attacks by using the X-Frame-Options.
例如,以下配置指定 Spring Security 不再指示浏览器阻止内容:
For example, the following configuration specifies that Spring Security should no longer instruct browsers to block the content:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.sameOrigin()
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<frame-options
policy="SAMEORIGIN" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
headers {
frameOptions {
sameOrigin = true
}
}
}
return http.build()
}
}
X-XSS-Protection
默认情况下,Spring Security 指示浏览器使用 <<headers-xss-protection,X-XSS-Protection 头> 来禁用 XSS 审核员。但是,你可以更改此默认值。例如,以下配置指定 Spring Security 指示兼容浏览器启用筛选,并阻止内容:
By default, Spring Security instructs browsers to disable the XSS Auditor by using <<headers-xss-protection,X-XSS-Protection header>. However, you can change this default. For example, the following configuration specifies that Spring Security instruct compatible browsers to enable filtering, and block the content:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.xssProtection(xss -> xss
.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<xss-protection headerValue="1; mode=block"/>
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
// ...
http {
headers {
xssProtection {
headerValue = XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK
}
}
}
return http.build()
}
}
Content Security Policy (CSP)
Spring Security 默认情况下并不添加 Content Security Policy ,因为在不知道应用程序的上下文的情况下不可能知道一个合理的默认值。Web 应用程序作者必须声明要实施或在受保护资源进行监视的安全策略(或策略)。
Spring Security does not add Content Security Policy by default, because a reasonable default is impossible to know without knowing the context of the application. The web application author must declare the security policy (or policies) to enforce or monitor for the protected resources.
考虑以下安全策略:
Consider the following security policy:
Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
鉴于之前的安全策略,你可以启用 CSP 头:
Given the preceding security policy, you can enable the CSP header:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<content-security-policy
policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
contentSecurityPolicy {
policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
}
}
}
return http.build()
}
}
要启用 CSP report-only
头,请提供以下配置:
To enable the CSP report-only
header, provide the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp
.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
.reportOnly()
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<content-security-policy
policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
report-only="true" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
contentSecurityPolicy {
policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
reportOnly = true
}
}
}
return http.build()
}
}
Referrer Policy
Spring Security 默认情况下并不添加 Referrer Policy 头。你可以使用配置启用引用人策略头:
Spring Security does not add Referrer Policy headers by default. You can enable the Referrer Policy header by using the configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicy.SAME_ORIGIN)
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<referrer-policy policy="same-origin" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
referrerPolicy {
policy = ReferrerPolicy.SAME_ORIGIN
}
}
}
return http.build()
}
}
Feature Policy
Spring Security 默认情况下并不添加 Feature Policy 头。考虑以下 Feature-Policy
头:
Spring Security does not add Feature Policy headers by default.
Consider the following Feature-Policy
header:
Feature-Policy: geolocation 'self'
你可以使用以下配置启用之前的特性策略头:
You can enable the preceding feature policy header by using the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.featurePolicy("geolocation 'self'")
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<feature-policy policy-directives="geolocation 'self'" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
featurePolicy("geolocation 'self'")
}
}
return http.build()
}
}
Permissions Policy
Spring Security 默认情况下并不添加 Permissions Policy 头。考虑以下 Permissions-Policy
头:
Spring Security does not add Permissions Policy headers by default.
Consider the following Permissions-Policy
header:
Permissions-Policy: geolocation=(self)
你可以使用以下配置启用之前的权限策略代码:
You can enable the preceding permissions policy header using the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.permissionsPolicy(permissions -> permissions
.policy("geolocation=(self)")
)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<permissions-policy policy="geolocation=(self)" />
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
permissionPolicy {
policy = "geolocation=(self)"
}
}
}
return http.build()
}
}
Clear Site Data
Spring Security 在默认情况下不会添加 Clear-Site-Data 标头。考虑一下以下 Clear-Site-Data 标头:
Spring Security does not add Clear-Site-Data headers by default. Consider the following Clear-Site-Data header:
Clear-Site-Data: "cache", "cookies"
你可以使用以下配置在注销时发送之前的头:
You can send the preceding header on log out with the following configuration:
-
Java
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.logout((logout) -> logout
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)))
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
logout {
addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(CACHE, COOKIES)))
}
}
return http.build()
}
}
Custom Headers
Spring Security 具有机制,便于将更常见的安全头添加到应用程序中。但是,它还提供钩子以启用添加自定义头。
Spring Security has mechanisms to make it convenient to add the more common security headers to your application. However, it also provides hooks to enable adding custom headers.
Static Headers
有时,你可能希望将开箱即用不支持的自定义安全头注入应用程序中。考虑以下自定义安全头:
There may be times when you wish to inject custom security headers that are not supported out of the box into your application. Consider the following custom security header:
X-Custom-Security-Header: header-value
鉴于之前的头,你可以使用以下配置将头添加到响应中:
Given the preceding header, you could add the headers to the response by using the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"))
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<header name="X-Custom-Security-Header" value="header-value"/>
</headers>
</http>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
addHeaderWriter(StaticHeadersWriter("X-Custom-Security-Header","header-value"))
}
}
return http.build()
}
}
Headers Writer
当命名空间或 Java 配置不支持你想要的头时,你可以创建一个自定义 HeadersWriter
实例,甚至提供 HeadersWriter
的自定义实现。
When the namespace or Java configuration does not support the headers you want, you can create a custom HeadersWriter
instance or even provide a custom implementation of the HeadersWriter
.
下一个示例使用 XFrameOptionsHeaderWriter
的自定义实例。如果你想显式配置 X-Frame-Options,可以通过以下配置完成:
The next example use a custom instance of XFrameOptionsHeaderWriter
.
If you wanted to explicitly configure X-Frame-Options, you could do so with the following configuration:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.headers(headers -> headers
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<header ref="frameOptionsWriter"/>
</headers>
</http>
<!-- Requires the c-namespace.
See https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-c-namespace
-->
<beans:bean id="frameOptionsWriter"
class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
c:frameOptionsMode="SAMEORIGIN"/>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
// ...
headers {
addHeaderWriter(XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
}
}
return http.build()
}
}
DelegatingRequestMatcherHeaderWriter
有时,你可能只想为某些请求编写头。例如,你可能只想保护你的登录页面不被框架。你可以使用 DelegatingRequestMatcherHeaderWriter
来做到这一点。
At times, you may want to write a header only for certain requests.
For example, perhaps you want to protect only your login page from being framed.
You could use the DelegatingRequestMatcherHeaderWriter
to do so.
以下配置示例使用 DelegatingRequestMatcherHeaderWriter
:
The following configuration example uses DelegatingRequestMatcherHeaderWriter
:
-
Java
-
XML
-
Kotlin
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
RequestMatcher matcher = new AntPathRequestMatcher("/login");
DelegatingRequestMatcherHeaderWriter headerWriter =
new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
http
// ...
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions.disable())
.addHeaderWriter(headerWriter)
);
return http.build();
}
}
<http>
<!-- ... -->
<headers>
<frame-options disabled="true"/>
<header ref="headerWriter"/>
</headers>
</http>
<beans:bean id="headerWriter"
class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
<beans:constructor-arg>
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
c:pattern="/login"/>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
</beans:constructor-arg>
</beans:bean>
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
val matcher: RequestMatcher = AntPathRequestMatcher("/login")
val headerWriter = DelegatingRequestMatcherHeaderWriter(matcher, XFrameOptionsHeaderWriter())
http {
headers {
frameOptions {
disable()
}
addHeaderWriter(headerWriter)
}
}
return http.build()
}
}