Adds support for Content Security Policy
Fixes gh-2342
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.security.config.annotation.web.configurers
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException
|
||||
import org.springframework.security.config.annotation.BaseSpringSpec
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||
@@ -24,6 +25,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Tim Ysewyn
|
||||
* @author Joe Grandja
|
||||
*/
|
||||
class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@@ -387,4 +389,68 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
.reportUri("http://example.net/pkp-report")
|
||||
}
|
||||
}
|
||||
|
||||
def "headers.contentSecurityPolicy default header"() {
|
||||
setup:
|
||||
loadConfig(ContentSecurityPolicyDefaultConfig)
|
||||
request.secure = true
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Content-Security-Policy': 'default-src \'self\'']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class ContentSecurityPolicyDefaultConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.contentSecurityPolicy("default-src 'self'");
|
||||
}
|
||||
}
|
||||
|
||||
def "headers.contentSecurityPolicy report-only header"() {
|
||||
setup:
|
||||
loadConfig(ContentSecurityPolicyReportOnlyConfig)
|
||||
request.secure = true
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['Content-Security-Policy-Report-Only': 'default-src \'self\'; script-src trustedscripts.example.com']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class ContentSecurityPolicyReportOnlyConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.contentSecurityPolicy("default-src 'self'; script-src trustedscripts.example.com").reportOnly();
|
||||
}
|
||||
}
|
||||
|
||||
def "headers.contentSecurityPolicy empty policyDirectives"() {
|
||||
when:
|
||||
loadConfig(ContentSecurityPolicyInvalidConfig)
|
||||
then:
|
||||
thrown(BeanCreationException)
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class ContentSecurityPolicyInvalidConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.contentSecurityPolicy("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -830,6 +830,84 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
expected.message.contains 'policy'
|
||||
}
|
||||
|
||||
def 'http headers defaults : content-security-policy'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'content-security-policy'('policy-directives':'default-src \'self\'')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders['Content-Security-Policy'] = 'default-src \'self\''
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def 'http headers disabled : content-security-policy not included'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'(disabled:true) {
|
||||
'content-security-policy'('policy-directives':'default-src \'self\'')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
then:
|
||||
!hf
|
||||
}
|
||||
|
||||
def 'http headers defaults disabled : content-security-policy only'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'content-security-policy'('policy-directives':'default-src \'self\'')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, ['Content-Security-Policy':'default-src \'self\''])
|
||||
}
|
||||
|
||||
def 'http headers defaults : content-security-policy with empty directives'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'content-security-policy'('policy-directives':'')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
then:
|
||||
thrown(BeanDefinitionParsingException)
|
||||
}
|
||||
|
||||
def 'http headers defaults : content-security-policy report-only=true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'content-security-policy'('policy-directives':'default-src https:; report-uri https://example.com/', 'report-only':true)
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
when:
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders['Content-Security-Policy-Report-Only'] = 'default-src https:; report-uri https://example.com/'
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def assertHeaders(MockHttpServletResponse response, Map<String,String> expected) {
|
||||
assert response.headerNames == expected.keySet()
|
||||
expected.each { headerName, value ->
|
||||
|
||||
Reference in New Issue
Block a user