SEC-2846: Security HTTP Response Headers Configuration Cleanup
This commit is contained in:
@@ -26,6 +26,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||
import org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
@@ -77,7 +78,10 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.headers().contentTypeOptions()
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.contentTypeOptions()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +99,10 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.headers().frameOptions()
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.frameOptions()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +121,10 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.headers().httpStrictTransportSecurity()
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.httpStrictTransportSecurity()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +144,10 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.headers().cacheControl()
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.cacheControl()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +165,37 @@ class HeadersConfigurerTests extends BaseSpringSpec {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.headers().xssProtection()
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.xssProtection()
|
||||
}
|
||||
}
|
||||
|
||||
def "headers custom x-frame-options"() {
|
||||
setup:
|
||||
loadConfig(HeadersCustomSameOriginConfig)
|
||||
request.secure = true
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(request,response,chain)
|
||||
then:
|
||||
responseHeaders == ['X-Content-Type-Options':'nosniff',
|
||||
'X-Frame-Options':'SAMEORIGIN',
|
||||
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
||||
'Expires' : '0',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block']
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class HeadersCustomSameOriginConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.headers()
|
||||
.frameOptions().sameOrigin()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.security.web.header.writers.frameoptions.StaticAllowF
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Tests to verify that all the functionality of <headers> attributes is present
|
||||
@@ -80,7 +81,8 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
protected void configure(HttpSecurity http) {
|
||||
http
|
||||
.headers()
|
||||
.addHeaderWriter(new CacheControlHeadersWriter())
|
||||
.defaultsDisabled()
|
||||
.cacheControl()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +102,8 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
protected void configure(HttpSecurity http) {
|
||||
http
|
||||
.headers()
|
||||
.addHeaderWriter(new HstsHeaderWriter())
|
||||
.defaultsDisabled()
|
||||
.httpStrictTransportSecurity()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +123,11 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
http
|
||||
.headers()
|
||||
// hsts@request-matcher-ref, hsts@max-age-seconds, hsts@include-subdomains
|
||||
// Additional Constructors are provided to leverage default values
|
||||
.addHeaderWriter(new HstsHeaderWriter(AnyRequestMatcher.INSTANCE, 15768000, false))
|
||||
.defaultsDisabled()
|
||||
.httpStrictTransportSecurity()
|
||||
.requestMatcher(AnyRequestMatcher.INSTANCE)
|
||||
.maxAgeInSeconds(15768000)
|
||||
.includeSubDomains(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +147,9 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
http
|
||||
.headers()
|
||||
// frame-options@policy=SAMEORIGIN
|
||||
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
|
||||
.defaultsDisabled()
|
||||
.frameOptions()
|
||||
.sameOrigin()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +172,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
http
|
||||
.headers()
|
||||
// frame-options@ref
|
||||
.defaultsDisabled()
|
||||
.addHeaderWriter(new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI("https://example.com"))))
|
||||
}
|
||||
}
|
||||
@@ -184,7 +193,8 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
http
|
||||
.headers()
|
||||
// xss-protection
|
||||
.addHeaderWriter(new XXssProtectionHeaderWriter())
|
||||
.defaultsDisabled()
|
||||
.xssProtection()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +214,10 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
http
|
||||
.headers()
|
||||
// xss-protection@enabled and xss-protection@block
|
||||
.addHeaderWriter(new XXssProtectionHeaderWriter(enabled:true,block:false))
|
||||
.defaultsDisabled()
|
||||
.xssProtection()
|
||||
.xssProtectionEnabled(true)
|
||||
.block(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +237,8 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
http
|
||||
.headers()
|
||||
// content-type-options
|
||||
.addHeaderWriter(new XContentTypeOptionsHeaderWriter())
|
||||
.defaultsDisabled()
|
||||
.contentTypeOptions()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,6 +259,7 @@ public class NamespaceHttpHeadersTests extends BaseSpringSpec {
|
||||
protected void configure(HttpSecurity http) {
|
||||
http
|
||||
.headers()
|
||||
.defaultsDisabled()
|
||||
.addHeaderWriter(new StaticHeadersWriter("customHeaderName", "customHeaderValue"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,13 @@ import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
* @author Rob Winch
|
||||
*/
|
||||
class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def defaultHeaders = ['X-Content-Type-Options':'nosniff',
|
||||
'X-Frame-Options':'DENY',
|
||||
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
||||
'Expires' : '0',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block']
|
||||
def 'headers disabled'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
@@ -62,13 +69,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, ['X-Content-Type-Options':'nosniff',
|
||||
'X-Frame-Options':'DENY',
|
||||
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
||||
'Expires' : '0',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block'])
|
||||
assertHeaders(response, defaultHeaders)
|
||||
}
|
||||
|
||||
def 'http headers with empty headers'() {
|
||||
@@ -82,18 +83,33 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, ['X-Content-Type-Options':'nosniff',
|
||||
'X-Frame-Options':'DENY',
|
||||
'Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains',
|
||||
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
||||
'Expires' : '0',
|
||||
'Pragma':'no-cache',
|
||||
'X-XSS-Protection' : '1; mode=block'])
|
||||
assertHeaders(response, defaultHeaders)
|
||||
}
|
||||
|
||||
def 'http headers frame-options@policy=SAMEORIGIN with defaults'() {
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'frame-options'(policy:'SAMEORIGIN')
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
|
||||
def hf = getFilter(HeaderWriterFilter)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders['X-Frame-Options'] = 'SAMEORIGIN'
|
||||
|
||||
expect:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
|
||||
// --- defaults disabled
|
||||
|
||||
def 'http headers content-type-options'() {
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'content-type-options'()
|
||||
}
|
||||
}
|
||||
@@ -109,7 +125,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
|
||||
def 'http headers frame-options defaults to DENY'() {
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'()
|
||||
}
|
||||
}
|
||||
@@ -125,7 +141,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
|
||||
def 'http headers frame-options DENY'() {
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'(policy : 'DENY')
|
||||
}
|
||||
}
|
||||
@@ -141,7 +157,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
|
||||
def 'http headers frame-options SAMEORIGIN'() {
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'(policy : 'SAMEORIGIN')
|
||||
}
|
||||
}
|
||||
@@ -158,7 +174,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers frame-options ALLOW-FROM no origin reports error'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'(policy : 'ALLOW-FROM', strategy : 'static')
|
||||
}
|
||||
}
|
||||
@@ -174,7 +190,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers frame-options ALLOW-FROM spaces only origin reports error'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'(policy : 'ALLOW-FROM', strategy: 'static', value : ' ')
|
||||
}
|
||||
}
|
||||
@@ -190,7 +206,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers frame-options ALLOW-FROM'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'(policy : 'ALLOW-FROM', strategy: 'static', value : 'https://example.com')
|
||||
}
|
||||
}
|
||||
@@ -207,7 +223,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers frame-options ALLOW-FROM with whitelist strategy'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'frame-options'(policy : 'ALLOW-FROM', strategy: 'whitelist', value : 'https://example.com')
|
||||
}
|
||||
}
|
||||
@@ -227,7 +243,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers header a=b'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'header'(name : 'a', value: 'b')
|
||||
}
|
||||
}
|
||||
@@ -244,7 +260,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers header a=b and c=d'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'header'(name : 'a', value: 'b')
|
||||
'header'(name : 'c', value: 'd')
|
||||
}
|
||||
@@ -262,7 +278,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers with ref'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'header'(ref:'headerWriter')
|
||||
}
|
||||
}
|
||||
@@ -282,7 +298,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers header no name produces error'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'header'(value: 'b')
|
||||
}
|
||||
}
|
||||
@@ -295,7 +311,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers header no value produces error'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'header'(name: 'a')
|
||||
}
|
||||
}
|
||||
@@ -308,7 +324,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers xss-protection defaults'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'xss-protection'()
|
||||
}
|
||||
}
|
||||
@@ -325,7 +341,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers xss-protection enabled=true'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'xss-protection'(enabled:'true')
|
||||
}
|
||||
}
|
||||
@@ -342,7 +358,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers xss-protection enabled=false'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'xss-protection'(enabled:'false')
|
||||
}
|
||||
}
|
||||
@@ -359,7 +375,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers xss-protection enabled=false and block=true produces error'() {
|
||||
when:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'xss-protection'(enabled:'false', block:'true')
|
||||
}
|
||||
}
|
||||
@@ -375,7 +391,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers cache-control'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'cache-control'()
|
||||
}
|
||||
}
|
||||
@@ -393,7 +409,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers hsts'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'hsts'()
|
||||
}
|
||||
}
|
||||
@@ -409,7 +425,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers hsts default only invokes on HttpServletRequest.isSecure = true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'hsts'()
|
||||
}
|
||||
}
|
||||
@@ -425,7 +441,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
def 'http headers hsts custom'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'headers'('defaults-disabled':true) {
|
||||
'hsts'('max-age-seconds':'1','include-subdomains':false, 'request-matcher-ref' : 'matcher')
|
||||
}
|
||||
}
|
||||
@@ -440,6 +456,187 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
|
||||
assertHeaders(response, ['Strict-Transport-Security': 'max-age=1'])
|
||||
}
|
||||
|
||||
// --- disable single default header ---
|
||||
|
||||
def 'http headers cache-controls@disabled=true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'cache-control'(disabled:true)
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders.remove('Cache-Control')
|
||||
expectedHeaders.remove('Expires')
|
||||
expectedHeaders.remove('Pragma')
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def 'http headers content-type-options@disabled=true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'content-type-options'(disabled:true)
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders.remove('X-Content-Type-Options')
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def 'http headers hsts@disabled=true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'hsts'(disabled:true)
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders.remove('Strict-Transport-Security')
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def 'http headers frame-options@disabled=true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'frame-options'(disabled:true)
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders.remove('X-Frame-Options')
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
def 'http headers xss-protection@disabled=true'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'xss-protection'(disabled:true)
|
||||
}
|
||||
}
|
||||
createAppContext()
|
||||
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
|
||||
MockHttpServletResponse response = new MockHttpServletResponse()
|
||||
def expectedHeaders = [:] << defaultHeaders
|
||||
expectedHeaders.remove('X-XSS-Protection')
|
||||
when:
|
||||
springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
|
||||
then:
|
||||
assertHeaders(response, expectedHeaders)
|
||||
}
|
||||
|
||||
// --- disable error handling ---
|
||||
|
||||
def 'http headers hsts@disabled=true no include-subdomains'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'hsts'(disabled:true,'include-subdomains':true)
|
||||
}
|
||||
}
|
||||
when:
|
||||
createAppContext()
|
||||
then:
|
||||
BeanDefinitionParsingException expected = thrown()
|
||||
expected.message.contains 'include-subdomains'
|
||||
}
|
||||
|
||||
def 'http headers hsts@disabled=true no max-age'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'hsts'(disabled:true,'max-age-seconds':123)
|
||||
}
|
||||
}
|
||||
when:
|
||||
createAppContext()
|
||||
then:
|
||||
BeanDefinitionParsingException expected = thrown()
|
||||
expected.message.contains 'max-age'
|
||||
}
|
||||
|
||||
def 'http headers hsts@disabled=true no matcher-ref'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'hsts'(disabled:true,'request-matcher-ref':'matcher')
|
||||
}
|
||||
}
|
||||
xml.'b:bean'(id: 'matcher', 'class': AnyRequestMatcher.name)
|
||||
when:
|
||||
createAppContext()
|
||||
then:
|
||||
BeanDefinitionParsingException expected = thrown()
|
||||
expected.message.contains 'request-matcher-ref'
|
||||
}
|
||||
|
||||
def 'http xss@disabled=true no enabled'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'xss-protection'(disabled:true,'enabled':true)
|
||||
}
|
||||
}
|
||||
when:
|
||||
createAppContext()
|
||||
then:
|
||||
BeanDefinitionParsingException expected = thrown()
|
||||
expected.message.contains 'enabled'
|
||||
}
|
||||
|
||||
def 'http xss@disabled=true no block'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'xss-protection'(disabled:true,'block':true)
|
||||
}
|
||||
}
|
||||
when:
|
||||
createAppContext()
|
||||
then:
|
||||
BeanDefinitionParsingException expected = thrown()
|
||||
expected.message.contains 'block'
|
||||
}
|
||||
|
||||
def 'http frame-options@disabled=true no policy'() {
|
||||
setup:
|
||||
httpAutoConfig {
|
||||
'headers'() {
|
||||
'frame-options'(disabled:true,'policy':'DENY')
|
||||
}
|
||||
}
|
||||
when:
|
||||
createAppContext()
|
||||
then:
|
||||
BeanDefinitionParsingException expected = thrown()
|
||||
expected.message.contains 'policy'
|
||||
}
|
||||
|
||||
def assertHeaders(MockHttpServletResponse response, Map<String,String> expected) {
|
||||
assert response.headerNames == expected.keySet()
|
||||
expected.each { headerName, value ->
|
||||
|
||||
Reference in New Issue
Block a user