From 238c22cd737f62b39bf98dde5752a517182bfaa8 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 16 Nov 2016 14:27:33 -0800 Subject: [PATCH] Polish content security policy contribution See gh-7373 See gh-7373 --- .../security/SecurityProperties.java | 11 +++++++---- .../SpringBootWebSecurityConfiguration.java | 10 ++++++---- ...SpringBootWebSecurityConfigurationTests.java | 17 ++++++++++------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java index 97d2ad4795f..e157173a7fa 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java @@ -175,15 +175,17 @@ public class SecurityProperties implements SecurityPrerequisite { } public enum ContentSecurityPolicyMode { + /** - * Use the {@code Content-Security-Policy} header. + * Use the 'Content-Security-Policy' header. */ DEFAULT, /** - * Use the {@code Content-Security-Policy-Report-Only} header. + * Use the 'Content-Security-Policy-Report-Only' header. */ REPORT_ONLY + } /** @@ -212,7 +214,7 @@ public class SecurityProperties implements SecurityPrerequisite { private String contentSecurityPolicy; /** - * Whether to use the "Content-Security-Policy" or "Content-Security-Policy-Report-Only" header. + * Security policy mode. */ private ContentSecurityPolicyMode contentSecurityPolicyMode = ContentSecurityPolicyMode.DEFAULT; @@ -265,7 +267,8 @@ public class SecurityProperties implements SecurityPrerequisite { return this.contentSecurityPolicyMode; } - public void setContentSecurityPolicyMode(ContentSecurityPolicyMode contentSecurityPolicyMode) { + public void setContentSecurityPolicyMode( + ContentSecurityPolicyMode contentSecurityPolicyMode) { this.contentSecurityPolicyMode = contentSecurityPolicyMode; } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java index daa5e3569af..0197ca2ee76 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers; +import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers.ContentSecurityPolicyMode; import org.springframework.boot.autoconfigure.web.ErrorController; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -109,12 +110,13 @@ public class SpringBootWebSecurityConfiguration { configurer.contentTypeOptions().disable(); } if (StringUtils.hasText(headers.getContentSecurityPolicy())) { - if (headers.getContentSecurityPolicyMode() == Headers.ContentSecurityPolicyMode.DEFAULT) { - configurer.contentSecurityPolicy(headers.getContentSecurityPolicy()); + String policyDirectives = headers.getContentSecurityPolicy(); + ContentSecurityPolicyMode mode = headers.getContentSecurityPolicyMode(); + if (mode == ContentSecurityPolicyMode.DEFAULT) { + configurer.contentSecurityPolicy(policyDirectives); } else { - assert headers.getContentSecurityPolicyMode() == Headers.ContentSecurityPolicyMode.REPORT_ONLY; - configurer.contentSecurityPolicy(headers.getContentSecurityPolicy()).reportOnly(); + configurer.contentSecurityPolicy(policyDirectives).reportOnly(); } } if (!headers.isXss()) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java index 23af97a970e..e20cbb74d99 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java @@ -214,7 +214,8 @@ public class SpringBootWebSecurityConfigurationTests { is(notNullValue()))) .andExpect(MockMvcResultMatchers.header().string("X-Frame-Options", is(notNullValue()))) - .andExpect(MockMvcResultMatchers.header().doesNotExist("Content-Security-Policy")); + .andExpect(MockMvcResultMatchers.header() + .doesNotExist("Content-Security-Policy")); } @Test @@ -250,9 +251,10 @@ public class SpringBootWebSecurityConfigurationTests { .getBean("springSecurityFilterChain", Filter.class)) .build(); mockMvc.perform(MockMvcRequestBuilders.get("/")) - .andExpect(MockMvcResultMatchers.header().string("Content-Security-Policy", - is("default-src 'self';"))) - .andExpect(MockMvcResultMatchers.header().doesNotExist("Content-Security-Policy-Report-Only")); + .andExpect(MockMvcResultMatchers.header() + .string("Content-Security-Policy", is("default-src 'self';"))) + .andExpect(MockMvcResultMatchers.header() + .doesNotExist("Content-Security-Policy-Report-Only")); } @Test @@ -266,9 +268,10 @@ public class SpringBootWebSecurityConfigurationTests { .getBean("springSecurityFilterChain", Filter.class)) .build(); mockMvc.perform(MockMvcRequestBuilders.get("/")) - .andExpect(MockMvcResultMatchers.header().string("Content-Security-Policy-Report-Only", - is("default-src 'self';"))) - .andExpect(MockMvcResultMatchers.header().doesNotExist("Content-Security-Policy")); + .andExpect(MockMvcResultMatchers.header().string( + "Content-Security-Policy-Report-Only", is("default-src 'self';"))) + .andExpect(MockMvcResultMatchers.header() + .doesNotExist("Content-Security-Policy")); } @Configuration