From fffcd23214dc60fe0da003cc1076bc50d9a6c0bd Mon Sep 17 00:00:00 2001 From: ctlove0523 <478309639@qq.com> Date: Wed, 28 Oct 2020 22:27:33 +0800 Subject: [PATCH 1/2] Allows SecureHeaders filter header values to be set per route. Fixes gh-2005 Fixes gh-2008 --- .../SecureHeadersGatewayFilterFactory.java | 158 ++++++++++++++++-- .../route/builder/GatewayFilterSpec.java | 15 +- ...eHeadersGatewayFilterFactoryUnitTests.java | 46 +++-- 3 files changed, 187 insertions(+), 32 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java index 3c9e7dff..1a05a8b9 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java @@ -32,7 +32,7 @@ import static org.springframework.cloud.gateway.support.GatewayToStringStyler.fi * * @author Spencer Gibb, Thirunavukkarasu Ravichandran */ -public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFactory { +public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFactory { /** * Xss-Protection header name. @@ -77,13 +77,12 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact private final SecureHeadersProperties properties; public SecureHeadersGatewayFilterFactory(SecureHeadersProperties properties) { + super(Config.class); this.properties = properties; } @Override - public GatewayFilter apply(Object config) { - // TODO: allow args to override properties - + public GatewayFilter apply(Config originalConfig) { return new GatewayFilter() { @Override public Mono filter(ServerWebExchange exchange, @@ -91,43 +90,38 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact HttpHeaders headers = exchange.getResponse().getHeaders(); List disabled = properties.getDisable(); + Config config = originalConfig.withDefaults(properties); if (isEnabled(disabled, X_XSS_PROTECTION_HEADER)) { - headers.add(X_XSS_PROTECTION_HEADER, - properties.getXssProtectionHeader()); + headers.add(X_XSS_PROTECTION_HEADER, config.getXssProtectionHeader()); } if (isEnabled(disabled, STRICT_TRANSPORT_SECURITY_HEADER)) { - headers.add(STRICT_TRANSPORT_SECURITY_HEADER, - properties.getStrictTransportSecurity()); + headers.add(STRICT_TRANSPORT_SECURITY_HEADER, config.getStrictTransportSecurity()); } if (isEnabled(disabled, X_FRAME_OPTIONS_HEADER)) { - headers.add(X_FRAME_OPTIONS_HEADER, properties.getFrameOptions()); + headers.add(X_FRAME_OPTIONS_HEADER, config.getFrameOptions()); } if (isEnabled(disabled, X_CONTENT_TYPE_OPTIONS_HEADER)) { - headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, - properties.getContentTypeOptions()); + headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, config.getContentTypeOptions()); } if (isEnabled(disabled, REFERRER_POLICY_HEADER)) { - headers.add(REFERRER_POLICY_HEADER, properties.getReferrerPolicy()); + headers.add(REFERRER_POLICY_HEADER, config.getReferrerPolicy()); } if (isEnabled(disabled, CONTENT_SECURITY_POLICY_HEADER)) { - headers.add(CONTENT_SECURITY_POLICY_HEADER, - properties.getContentSecurityPolicy()); + headers.add(CONTENT_SECURITY_POLICY_HEADER, config.getContentSecurityPolicy()); } if (isEnabled(disabled, X_DOWNLOAD_OPTIONS_HEADER)) { - headers.add(X_DOWNLOAD_OPTIONS_HEADER, - properties.getDownloadOptions()); + headers.add(X_DOWNLOAD_OPTIONS_HEADER, config.getDownloadOptions()); } if (isEnabled(disabled, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)) { - headers.add(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, - properties.getPermittedCrossDomainPolicies()); + headers.add(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, config.getPermittedCrossDomainPolicies()); } return chain.filter(exchange); @@ -145,4 +139,132 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact return !disabledHeaders.contains(header.toLowerCase()); } + public static class Config { + + private String xssProtectionHeader; + + private String strictTransportSecurity; + + private String frameOptions; + + private String contentTypeOptions; + + private String referrerPolicy; + + private String contentSecurityPolicy; + + private String downloadOptions; + + private String permittedCrossDomainPolicies; + + public Config withDefaults(SecureHeadersProperties properties) { + Config config = new Config(); + config.setXssProtectionHeader(xssProtectionHeader); + config.setStrictTransportSecurity(strictTransportSecurity); + config.setFrameOptions(frameOptions); + config.setContentTypeOptions(contentTypeOptions); + config.setReferrerPolicy(referrerPolicy); + config.setContentSecurityPolicy(contentSecurityPolicy); + config.setDownloadOptions(downloadOptions); + config.setPermittedCrossDomainPolicies(permittedCrossDomainPolicies); + + if (config.xssProtectionHeader == null) { + config.xssProtectionHeader = properties.getXssProtectionHeader(); + } + + if (config.strictTransportSecurity == null) { + config.strictTransportSecurity = properties.getStrictTransportSecurity(); + } + + if (config.frameOptions == null) { + config.frameOptions = properties.getFrameOptions(); + } + + if (config.contentTypeOptions == null) { + config.contentTypeOptions = properties.getContentTypeOptions(); + } + + if (config.referrerPolicy == null) { + config.referrerPolicy = properties.getReferrerPolicy(); + } + + if (config.contentSecurityPolicy == null) { + config.contentSecurityPolicy = properties.getContentSecurityPolicy(); + } + + if (config.downloadOptions == null) { + config.downloadOptions = properties.getDownloadOptions(); + } + + if (config.permittedCrossDomainPolicies == null) { + config.permittedCrossDomainPolicies = properties.getPermittedCrossDomainPolicies(); + } + return config; + } + + public String getXssProtectionHeader() { + return xssProtectionHeader; + } + + public void setXssProtectionHeader(String xssProtectionHeader) { + this.xssProtectionHeader = xssProtectionHeader; + } + + public String getStrictTransportSecurity() { + return strictTransportSecurity; + } + + public void setStrictTransportSecurity(String strictTransportSecurity) { + this.strictTransportSecurity = strictTransportSecurity; + } + + public String getFrameOptions() { + return frameOptions; + } + + public void setFrameOptions(String frameOptions) { + this.frameOptions = frameOptions; + } + + public String getContentTypeOptions() { + return contentTypeOptions; + } + + public void setContentTypeOptions(String contentTypeOptions) { + this.contentTypeOptions = contentTypeOptions; + } + + public String getReferrerPolicy() { + return referrerPolicy; + } + + public void setReferrerPolicy(String referrerPolicy) { + this.referrerPolicy = referrerPolicy; + } + + public String getContentSecurityPolicy() { + return contentSecurityPolicy; + } + + public void setContentSecurityPolicy(String contentSecurityPolicy) { + this.contentSecurityPolicy = contentSecurityPolicy; + } + + public String getDownloadOptions() { + return downloadOptions; + } + + public void setDownloadOptions(String downloadOptions) { + this.downloadOptions = downloadOptions; + } + + public String getPermittedCrossDomainPolicies() { + return permittedCrossDomainPolicies; + } + + public void setPermittedCrossDomainPolicies(String permittedCrossDomainPolicies) { + this.permittedCrossDomainPolicies = permittedCrossDomainPolicies; + } + + } } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java index d990f46c..426e404c 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java @@ -565,10 +565,19 @@ public class GatewayFilterSpec extends UriSpec { * post. * @return a {@link GatewayFilterSpec} that can be used to apply additional filters */ - @SuppressWarnings("unchecked") public GatewayFilterSpec secureHeaders() { - return filter(getBean(SecureHeadersGatewayFilterFactory.class).apply(c -> { - })); + return filter(getBean(SecureHeadersGatewayFilterFactory.class).apply(config -> {})); + } + + /** + * A filter that adds a number of headers to the response at the reccomendation from + * this blog + * post. + * @param configConsumer self define headers + * @return a {@link GatewayFilterSpec} that can be used to apply additional filters + */ + public GatewayFilterSpec secureHeaders(Consumer configConsumer) { + return filter(getBean(SecureHeadersGatewayFilterFactory.class).apply(configConsumer)); } /** diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java index b6699aad..4e3fe555 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java @@ -24,7 +24,6 @@ import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory.NameConfig; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; @@ -35,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory.CONTENT_SECURITY_POLICY_HEADER; +import static org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory.Config; import static org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory.REFERRER_POLICY_HEADER; import static org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory.STRICT_TRANSPORT_SECURITY_HEADER; import static org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory.X_CONTENT_TYPE_OPTIONS_HEADER; @@ -71,9 +71,7 @@ public class SecureHeadersGatewayFilterFactoryUnitTests { public void addAllHeadersIfNothingIsDisabled() { SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory( new SecureHeadersProperties()); - NameConfig config = new NameConfig(); - config.setName("SecureHeadersGatewayFilter"); - filter = filterFactory.apply(config); + filter = filterFactory.apply(new Config()); filter.filter(exchange, filterChain); @@ -93,11 +91,8 @@ public class SecureHeadersGatewayFilterFactoryUnitTests { "content-security-policy", "x-download-options", "x-permitted-cross-domain-policies")); - SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory( - properties); - NameConfig config = new NameConfig(); - config.setName("SecureHeadersGatewayFilter"); - filter = filterFactory.apply(config); + SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory(properties); + filter = filterFactory.apply(new Config()); filter.filter(exchange, filterChain); @@ -110,10 +105,39 @@ public class SecureHeadersGatewayFilterFactoryUnitTests { } + @Test + public void overrideSomeHeaders() { + SecureHeadersProperties properties = new SecureHeadersProperties(); + SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory( + new SecureHeadersProperties()); + Config config = new Config(); + config.setStrictTransportSecurity("max-age=65535"); + config.setReferrerPolicy("referrer"); + filter = filterFactory.apply(config); + + filter.filter(exchange, filterChain); + + ServerHttpResponse response = captor.getValue().getResponse(); + assertThat(response.getHeaders()).containsKeys(X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER, + X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER, + CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER); + + assertThat(response.getHeaders().get(STRICT_TRANSPORT_SECURITY_HEADER)).containsOnly("max-age=65535"); + assertThat(response.getHeaders().get(REFERRER_POLICY_HEADER)).containsOnly("referrer"); + + assertThat(response.getHeaders().get(X_XSS_PROTECTION_HEADER)).containsOnly(properties.getXssProtectionHeader()); + assertThat(response.getHeaders().get(X_FRAME_OPTIONS_HEADER)).containsOnly(properties.getFrameOptions()); + assertThat(response.getHeaders().get(X_CONTENT_TYPE_OPTIONS_HEADER)).containsOnly(properties.getContentTypeOptions()); + assertThat(response.getHeaders().get(CONTENT_SECURITY_POLICY_HEADER)).containsOnly(properties.getContentSecurityPolicy()); + assertThat(response.getHeaders().get(X_DOWNLOAD_OPTIONS_HEADER)).containsOnly(properties.getDownloadOptions()); + assertThat(response.getHeaders().get(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)).containsOnly(properties.getPermittedCrossDomainPolicies()); + + + } + @Test public void toStringFormat() { - GatewayFilter filter = new SecureHeadersGatewayFilterFactory( - new SecureHeadersProperties()).apply(""); + GatewayFilter filter = new SecureHeadersGatewayFilterFactory(new SecureHeadersProperties()).apply(new Config()); Assertions.assertThat(filter.toString()).contains("SecureHeaders"); } From 9a5ed3522bf2061dbf076c283a5d6909ecfb3f98 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Mon, 2 Nov 2020 14:49:33 -0500 Subject: [PATCH 2/2] formatting --- .../SecureHeadersGatewayFilterFactory.java | 19 ++++++--- .../route/builder/GatewayFilterSpec.java | 9 +++-- ...ReactiveLoadBalancerClientFilterTests.java | 9 +++-- ...eHeadersGatewayFilterFactoryUnitTests.java | 39 ++++++++++++------- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java index 1a05a8b9..3f755b11 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactory.java @@ -32,7 +32,8 @@ import static org.springframework.cloud.gateway.support.GatewayToStringStyler.fi * * @author Spencer Gibb, Thirunavukkarasu Ravichandran */ -public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFactory { +public class SecureHeadersGatewayFilterFactory + extends AbstractGatewayFilterFactory { /** * Xss-Protection header name. @@ -97,7 +98,8 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact } if (isEnabled(disabled, STRICT_TRANSPORT_SECURITY_HEADER)) { - headers.add(STRICT_TRANSPORT_SECURITY_HEADER, config.getStrictTransportSecurity()); + headers.add(STRICT_TRANSPORT_SECURITY_HEADER, + config.getStrictTransportSecurity()); } if (isEnabled(disabled, X_FRAME_OPTIONS_HEADER)) { @@ -105,7 +107,8 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact } if (isEnabled(disabled, X_CONTENT_TYPE_OPTIONS_HEADER)) { - headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, config.getContentTypeOptions()); + headers.add(X_CONTENT_TYPE_OPTIONS_HEADER, + config.getContentTypeOptions()); } if (isEnabled(disabled, REFERRER_POLICY_HEADER)) { @@ -113,7 +116,8 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact } if (isEnabled(disabled, CONTENT_SECURITY_POLICY_HEADER)) { - headers.add(CONTENT_SECURITY_POLICY_HEADER, config.getContentSecurityPolicy()); + headers.add(CONTENT_SECURITY_POLICY_HEADER, + config.getContentSecurityPolicy()); } if (isEnabled(disabled, X_DOWNLOAD_OPTIONS_HEADER)) { @@ -121,7 +125,8 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact } if (isEnabled(disabled, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)) { - headers.add(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, config.getPermittedCrossDomainPolicies()); + headers.add(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER, + config.getPermittedCrossDomainPolicies()); } return chain.filter(exchange); @@ -197,7 +202,8 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact } if (config.permittedCrossDomainPolicies == null) { - config.permittedCrossDomainPolicies = properties.getPermittedCrossDomainPolicies(); + config.permittedCrossDomainPolicies = properties + .getPermittedCrossDomainPolicies(); } return config; } @@ -267,4 +273,5 @@ public class SecureHeadersGatewayFilterFactory extends AbstractGatewayFilterFact } } + } diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java index 426e404c..dd061467 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java @@ -566,7 +566,8 @@ public class GatewayFilterSpec extends UriSpec { * @return a {@link GatewayFilterSpec} that can be used to apply additional filters */ public GatewayFilterSpec secureHeaders() { - return filter(getBean(SecureHeadersGatewayFilterFactory.class).apply(config -> {})); + return filter(getBean(SecureHeadersGatewayFilterFactory.class).apply(config -> { + })); } /** @@ -576,8 +577,10 @@ public class GatewayFilterSpec extends UriSpec { * @param configConsumer self define headers * @return a {@link GatewayFilterSpec} that can be used to apply additional filters */ - public GatewayFilterSpec secureHeaders(Consumer configConsumer) { - return filter(getBean(SecureHeadersGatewayFilterFactory.class).apply(configConsumer)); + public GatewayFilterSpec secureHeaders( + Consumer configConsumer) { + return filter( + getBean(SecureHeadersGatewayFilterFactory.class).apply(configConsumer)); } /** diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilterTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilterTests.java index 49a8441c..1f1b7048 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilterTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/ReactiveLoadBalancerClientFilterTests.java @@ -273,9 +273,12 @@ public class ReactiveLoadBalancerClientFilterTests { ServiceInstance serviceInstance = new DefaultServiceInstance("myservice1", "myservice", "localhost", 8080, false); when(clientFactory.getInstance("myservice", - ReactorServiceInstanceLoadBalancer.class)).thenReturn( - new RoundRobinLoadBalancer(ServiceInstanceListSuppliers - .toProvider("myservice", serviceInstance), "myservice", -1)); + ReactorServiceInstanceLoadBalancer.class)) + .thenReturn( + new RoundRobinLoadBalancer( + ServiceInstanceListSuppliers + .toProvider("myservice", serviceInstance), + "myservice", -1)); when(chain.filter(exchange)).thenReturn(Mono.empty()); filter.filter(exchange, chain).block(); diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java index 4e3fe555..41cbf7ad 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/SecureHeadersGatewayFilterFactoryUnitTests.java @@ -91,7 +91,8 @@ public class SecureHeadersGatewayFilterFactoryUnitTests { "content-security-policy", "x-download-options", "x-permitted-cross-domain-policies")); - SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory(properties); + SecureHeadersGatewayFilterFactory filterFactory = new SecureHeadersGatewayFilterFactory( + properties); filter = filterFactory.apply(new Config()); filter.filter(exchange, filterChain); @@ -118,26 +119,36 @@ public class SecureHeadersGatewayFilterFactoryUnitTests { filter.filter(exchange, filterChain); ServerHttpResponse response = captor.getValue().getResponse(); - assertThat(response.getHeaders()).containsKeys(X_XSS_PROTECTION_HEADER, STRICT_TRANSPORT_SECURITY_HEADER, - X_FRAME_OPTIONS_HEADER, X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER, - CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER); + assertThat(response.getHeaders()).containsKeys(X_XSS_PROTECTION_HEADER, + STRICT_TRANSPORT_SECURITY_HEADER, X_FRAME_OPTIONS_HEADER, + X_CONTENT_TYPE_OPTIONS_HEADER, REFERRER_POLICY_HEADER, + CONTENT_SECURITY_POLICY_HEADER, X_DOWNLOAD_OPTIONS_HEADER, + X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER); - assertThat(response.getHeaders().get(STRICT_TRANSPORT_SECURITY_HEADER)).containsOnly("max-age=65535"); - assertThat(response.getHeaders().get(REFERRER_POLICY_HEADER)).containsOnly("referrer"); - - assertThat(response.getHeaders().get(X_XSS_PROTECTION_HEADER)).containsOnly(properties.getXssProtectionHeader()); - assertThat(response.getHeaders().get(X_FRAME_OPTIONS_HEADER)).containsOnly(properties.getFrameOptions()); - assertThat(response.getHeaders().get(X_CONTENT_TYPE_OPTIONS_HEADER)).containsOnly(properties.getContentTypeOptions()); - assertThat(response.getHeaders().get(CONTENT_SECURITY_POLICY_HEADER)).containsOnly(properties.getContentSecurityPolicy()); - assertThat(response.getHeaders().get(X_DOWNLOAD_OPTIONS_HEADER)).containsOnly(properties.getDownloadOptions()); - assertThat(response.getHeaders().get(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)).containsOnly(properties.getPermittedCrossDomainPolicies()); + assertThat(response.getHeaders().get(STRICT_TRANSPORT_SECURITY_HEADER)) + .containsOnly("max-age=65535"); + assertThat(response.getHeaders().get(REFERRER_POLICY_HEADER)) + .containsOnly("referrer"); + assertThat(response.getHeaders().get(X_XSS_PROTECTION_HEADER)) + .containsOnly(properties.getXssProtectionHeader()); + assertThat(response.getHeaders().get(X_FRAME_OPTIONS_HEADER)) + .containsOnly(properties.getFrameOptions()); + assertThat(response.getHeaders().get(X_CONTENT_TYPE_OPTIONS_HEADER)) + .containsOnly(properties.getContentTypeOptions()); + assertThat(response.getHeaders().get(CONTENT_SECURITY_POLICY_HEADER)) + .containsOnly(properties.getContentSecurityPolicy()); + assertThat(response.getHeaders().get(X_DOWNLOAD_OPTIONS_HEADER)) + .containsOnly(properties.getDownloadOptions()); + assertThat(response.getHeaders().get(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER)) + .containsOnly(properties.getPermittedCrossDomainPolicies()); } @Test public void toStringFormat() { - GatewayFilter filter = new SecureHeadersGatewayFilterFactory(new SecureHeadersProperties()).apply(new Config()); + GatewayFilter filter = new SecureHeadersGatewayFilterFactory( + new SecureHeadersProperties()).apply(new Config()); Assertions.assertThat(filter.toString()).contains("SecureHeaders"); }