Security HTTP Response Headers
您可以使用 Security HTTP Response Headers 来增加 Web 应用程序的安全性。本节专门介绍基于 WebFlux 的安全 HTTP 响应头支持。
Default Security Headers
Spring Security 提供一个 default set of Security HTTP Response Headers 来提供安全的默认值。虽然每个头都可认为是最佳实践,但应注意并非所有客户端都使用这些头,因此建议进行其他测试。
你可以自定义特定头。例如,假设你想要使用默认设置,但你希望为 xref:servlet/exploits/headers.adoc#servlet-headers-frame-options[X-Frame-Options
指定 SAMEORIGIN
。
你可以使用以下配置来实现:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.mode(Mode.SAMEORIGIN)
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
frameOptions {
mode = Mode.SAMEORIGIN
}
}
}
}
如果您不想添加默认标头并希望明确控制应该使用什么内容,您可以禁用默认标头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers.disable());
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
disable()
}
}
}
Cache Control
Spring Security 默认包含 Cache Control 头。
但是,如果您实际上希望缓存特定响应,您的应用程序可以选择性地将它们添加到 ServerHttpResponse
以覆盖 Spring Security 设置的标头。这有助于确保 CSS、JavaScript 和图像等内容得到正确缓存。
当使用 Spring WebFlux 时,您通常会在您的配置中这样做。您可以在 Spring 参考文档的 Static Resources 部分中找到有关如何执行此操作的详细信息。
如有必要,你还可以禁用 Spring Security 的缓存控制 HTTP 响应头。
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.cache(cache -> cache.disable())
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
cache {
disable()
}
}
}
}
Content Type Options
默认情况下,Spring Security 包含 Content-Type 头部。但是,您可以禁用它:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
contentTypeOptions {
disable()
}
}
}
}
HTTP Strict Transport Security (HSTS)
默认情况下,Spring Security 提供 Strict Transport Security 头部。但是,您可以明确自定义结果。例如,以下示例明确提供了 HSTS:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.hsts(hsts -> hsts
.includeSubdomains(true)
.preload(true)
.maxAge(Duration.ofDays(365))
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
hsts {
includeSubdomains = true
preload = true
maxAge = Duration.ofDays(365)
}
}
}
}
X-Frame-Options
默认情况下,Spring Security 通过使用 xref:features/exploits/headers.adoc#headers-frame-options[X-Frame-Options
禁用了 iframe 中的渲染。
您可以自定义 frame 选项以使用相同来源:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.frameOptions(frameOptions -> frameOptions
.mode(SAMEORIGIN)
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
frameOptions {
mode = SAMEORIGIN
}
}
}
}
X-XSS-Protection
默认情况下,Spring Security 指示浏览器使用 <<headers-xss-protection,X-XSS-Protection header> 禁用 XSS 审计器。您可以完全禁用 X-XSS-Protection
标头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.xssProtection(xssProtection -> xssProtection.disable())
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
xssProtection {
disable()
}
}
}
}
您还可以更改标头值:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.xssProtection(xssProtection -> xssProtection.headerValue(XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK))
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
xssProtection {
headerValue = XXssProtectionServerHttpHeadersWriter.HeaderValue.ENABLED_MODE_BLOCK
}
}
}
}
Content Security Policy (CSP)
默认情况下,Spring Security 不添加 Content Security Policy,因为合理的默认值不可能在没有应用程序上下文的情况下得知。Web 应用程序作者必须声明要为受保护资源强制执行和/或监视的安全策略。
例如,考虑以下安全策略:
Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
鉴于上述策略,您可以启用 CSP 标头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.contentSecurityPolicy(policy -> policy
.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
contentSecurityPolicy {
policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
}
}
}
}
要启用 CSP report-only
头,请提供以下配置:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.contentSecurityPolicy(policy -> policy
.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
.reportOnly()
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
contentSecurityPolicy {
policyDirectives = "script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
reportOnly = true
}
}
}
}
Referrer Policy
Spring Security 默认情况下添加 Referrer Policy 头部,其指令为 no-referrer
。您可以按照如下所示使用配置更改引荐策略报头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicy.SAME_ORIGIN)
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
referrerPolicy {
policy = ReferrerPolicy.SAME_ORIGIN
}
}
}
}
Feature Policy
默认情况下,Spring Security 不添加 Feature Policy 头部。请考虑以下 Feature-Policy
头部:
Feature-Policy: geolocation 'self'
您可以启用上述特性策略标头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.featurePolicy("geolocation 'self'")
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
featurePolicy("geolocation 'self'")
}
}
}
Permissions Policy
默认情况下,Spring Security 不添加 Permissions Policy 头部。请考虑以下 Permissions-Policy
头部:
Permissions-Policy: geolocation=(self)
您可以启用前置权限策略标头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
// ...
.headers(headers -> headers
.permissionsPolicy(permissions -> permissions
.policy("geolocation=(self)")
)
);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http {
// ...
headers {
permissionsPolicy {
policy = "geolocation=(self)"
}
}
}
}
Clear Site Data
默认情况下,Spring Security 不添加 Clear-Site-Data 头部。请考虑以下 Clear-Site-Data
头部:
Clear-Site-Data: "cache", "cookies"
您可以在注销时发送 Clear-Site-Data
标头:
-
Java
-
Kotlin
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
ServerLogoutHandler securityContext = new SecurityContextServerLogoutHandler();
ClearSiteDataServerHttpHeadersWriter writer = new ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES);
ServerLogoutHandler clearSiteData = new HeaderWriterServerLogoutHandler(writer);
DelegatingServerLogoutHandler logoutHandler = new DelegatingServerLogoutHandler(securityContext, clearSiteData);
http
// ...
.logout()
.logoutHandler(logoutHandler);
return http.build();
}
@Bean
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
val securityContext: ServerLogoutHandler = SecurityContextServerLogoutHandler()
val writer = ClearSiteDataServerHttpHeadersWriter(CACHE, COOKIES)
val clearSiteData: ServerLogoutHandler = HeaderWriterServerLogoutHandler(writer)
val customLogoutHandler = DelegatingServerLogoutHandler(securityContext, clearSiteData)
return http {
// ...
logout {
logoutHandler = customLogoutHandler
}
}
}