安全 HTTP 響應頭
您可以使用 安全 HTTP 響應頭 來提高 Web 應用程式的安全性。本節專門介紹基於 WebFlux 的安全 HTTP 響應頭支援。
預設安全頭
Spring Security 提供了一組預設的安全 HTTP 響應頭以提供安全的預設值。儘管這些頭都被認為是最佳實踐,但應注意並非所有客戶端都使用這些頭,因此鼓勵進行額外的測試。
您可以自定義特定的頭。例如,假設您想要預設值,但希望為 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()
}
}
}
快取控制
Spring Security 預設包含 快取控制 頭。
但是,如果您確實想快取特定響應,您的應用程式可以選擇性地將其新增到 ServerHttpResponse 以覆蓋 Spring Security 設定的頭。這對於確保 CSS、JavaScript 和影像等內容得到正確快取非常有用。
使用 Spring WebFlux 時,您通常在配置中執行此操作。您可以在 Spring 參考文件的 靜態資源 部分找到如何執行此操作的詳細資訊。
如有必要,您還可以停用 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()
}
}
}
}
內容型別選項
預設情況下,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 嚴格傳輸安全 (HSTS)
預設情況下,Spring 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 透過使用 X-Frame-Options 停用在 iframe 中渲染。
您可以自定義框架選項以使用相同來源。
-
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 透過使用 <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
}
}
}
}
內容安全策略 (CSP)
預設情況下,Spring Security 不新增 內容安全策略,因為在沒有應用程式上下文的情況下無法知道合理的預設值。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。您可以使用如下所示的配置更改 Referrer Policy 頭:
-
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'
您可以啟用上述 Feature Policy 頭。
-
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)
您可以啟用上述 Permissions Policy 頭。
-
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
}
}
}