对于最新的稳定版本,请使用 Spring Security 6.3.1

对于最新的稳定版本,请使用 Spring Security 6.3.1

安全 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
            }
        }
    }
}

如果不希望添加默认值,并希望显式控制应使用的内容,则可以禁用默认值。 下面提供了一个示例:

禁用 HTTP 安全响应标头
  • 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 Reference 文档的 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()
            }
        }
    }
}

内容类型选项

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 提供 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-选项

默认情况下,Spring Security 使用 X-Frame-Options 禁用 iframe 中的渲染。

您可以使用以下命令自定义帧选项以使用相同的源:

X-Frame-选项:SAMEORIGIN
  • 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保护

默认情况下,Spring Security 指示浏览器使用 <<headers-xss-protection,X-XSS-Protection header> 阻止反射的 XSS 攻击。 您可以使用以下配置禁用:X-XSS-Protection

X-XSS-保护定制
  • 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()
            }
        }
    }
}

内容安全策略 (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
            }
        }
    }
}

推荐人政策

默认情况下,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
            }
        }
    }
}

功能策略

默认情况下,Spring Security 不会添加功能策略标头。 以下标头: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'")
        }
    }
}

权限策略

默认情况下,Spring Security 不会添加权限策略标头。 以下标头: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)"
            }
        }
    }
}

清除网站数据

默认情况下,Spring Security 不会添加 Clear-Site-Data 标头。 以下 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
        }
    }
}

跨域策略

Spring Security 为添加一些跨域策略标头提供了内置支持,这些标头是:

Cross-Origin-Opener-Policy
Cross-Origin-Embedder-Policy
Cross-Origin-Resource-Policy

默认情况下,Spring Security 不会添加跨域策略标头。 可以使用以下配置添加标头:

跨域策略
  • Java

  • Kotlin

@EnableWebFluxSecurity
@EnableWebFlux
public class WebSecurityConfig {

    @Bean
    SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
        http.headers((headers) -> headers
                .crossOriginOpenerPolicy(CrossOriginOpenerPolicy.SAME_ORIGIN)
                .crossOriginEmbedderPolicy(CrossOriginEmbedderPolicy.REQUIRE_CORP)
                .crossOriginResourcePolicy(CrossOriginResourcePolicy.SAME_ORIGIN));
        return http.build();
    }
}
@EnableWebFluxSecurity
@EnableWebFlux
open class CrossOriginPoliciesCustomConfig {
    @Bean
    open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
        return http {
            headers {
                crossOriginOpenerPolicy(CrossOriginOpenerPolicy.SAME_ORIGIN)
                crossOriginEmbedderPolicy(CrossOriginEmbedderPolicy.REQUIRE_CORP)
                crossOriginResourcePolicy(CrossOriginResourcePolicy.SAME_ORIGIN)
            }
        }
    }
}

此配置将使用提供的值编写标头:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Resource-Policy: same-origin