From 73345e74347fb5cfbd10c290da26270bb778b13e Mon Sep 17 00:00:00 2001
From: Rob Winch
Date: Thu, 24 May 2018 09:35:27 -0500
Subject: [PATCH] Add Cross Site Tracing (XST) & HTTP Method Tampering
Protection
Fixes: gh-5377
---
.../configurers/CsrfConfigurerTests.groovy | 17 ++++-
.../NamespaceHttpFirewallTests.groovy | 2 +-
.../NamespaceHttpPortMappingsTests.groovy | 2 +-
.../NamespaceRememberMeTests.groovy | 2 +-
.../RememberMeConfigurerTests.groovy | 2 +-
.../http/AbstractHttpConfigTests.groovy | 2 +-
.../config/http/HttpHeadersConfigTests.groovy | 74 +++++++++---------
.../config/http/MiscHttpConfigTests.groovy | 2 +-
.../http/MultiHttpBlockConfigTests.groovy | 4 +-
.../http/SessionManagementConfigTests.groovy | 12 +--
.../config/FilterChainProxyConfigTests.java | 2 +-
.../web/builders/WebSecurityTests.java | 2 +-
.../WebSecurityConfigurationTests.java | 2 +-
.../configurers/AuthorizeRequestsTests.java | 2 +-
.../HttpSecurityAntMatchersTests.java | 2 +-
.../configurers/HttpSecurityLogoutTests.java | 2 +-
.../HttpSecurityRequestMatchersTests.java | 2 +-
...ionManagementConfigurerServlet31Tests.java | 4 +-
.../UrlAuthorizationConfigurerTests.java | 4 +-
.../client/OAuth2ClientConfigurerTests.java | 2 +-
.../client/OAuth2LoginConfigurerTests.java | 2 +-
...WebSocketMessageBrokerConfigurerTests.java | 2 +-
.../core/GrantedAuthorityDefaultsJcTests.java | 2 +-
.../GrantedAuthorityDefaultsXmlTests.java | 2 +-
...tadataSourceBeanDefinitionParserTests.java | 2 +-
.../config/http/NamespaceHttpBasicTests.java | 2 +-
...SessionManagementConfigServlet31Tests.java | 6 +-
.../CustomHttpSecurityConfigurerTests.java | 2 +-
.../http/CsrfConfigTests-AutoConfig.xml | 5 ++
.../http/CsrfConfigTests-CsrfEnabled.xml | 5 ++
.../_includes/web/security-filter-chain.adoc | 39 ++++++++++
.../security/web/FilterChainProxy.java | 2 +-
.../web/firewall/StrictHttpFirewall.java | 72 ++++++++++++++++++
.../security/web/FilterChainProxyTests.java | 2 +-
.../web/firewall/StrictHttpFirewallTests.java | 75 ++++++++++++++++---
35 files changed, 276 insertions(+), 87 deletions(-)
diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy
index 05ddb22564..0628529318 100644
--- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/CsrfConfigurerTests.groovy
@@ -15,7 +15,10 @@
*/
package org.springframework.security.config.annotation.web.configurers
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
import org.springframework.security.core.userdetails.PasswordEncodedUser
+import org.springframework.security.web.firewall.StrictHttpFirewall
import javax.servlet.http.HttpServletResponse
@@ -44,7 +47,7 @@ class CsrfConfigurerTests extends BaseSpringSpec {
@Unroll
def "csrf applied by default"() {
setup:
- loadConfig(CsrfAppliedDefaultConfig)
+ loadConfig(CsrfAppliedDefaultConfig, AllowHttpMethodsFirewallConfig)
request.method = httpMethod
clearCsrfToken()
when:
@@ -66,11 +69,21 @@ class CsrfConfigurerTests extends BaseSpringSpec {
def "csrf default creates CsrfRequestDataValueProcessor"() {
when:
- loadConfig(CsrfAppliedDefaultConfig)
+ loadConfig(CsrfAppliedDefaultConfig, AllowHttpMethodsFirewallConfig)
then:
context.getBean(RequestDataValueProcessor)
}
+ @Configuration
+ static class AllowHttpMethodsFirewallConfig {
+ @Bean
+ StrictHttpFirewall strictHttpFirewall() {
+ StrictHttpFirewall result = new StrictHttpFirewall();
+ result.setAllowedHttpMethods(StrictHttpFirewall.ALLOW_ANY_HTTP_METHOD);
+ return result;
+ }
+ }
+
@EnableWebSecurity
static class CsrfAppliedDefaultConfig extends WebSecurityConfigurerAdapter {
diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.groovy
index 3ace0a8dc5..54d9e16b97 100644
--- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpFirewallTests.groovy
@@ -46,7 +46,7 @@ public class NamespaceHttpFirewallTests extends BaseSpringSpec {
MockFilterChain chain
def setup() {
- request = new MockHttpServletRequest()
+ request = new MockHttpServletRequest("GET", "")
response = new MockHttpServletResponse()
chain = new MockFilterChain()
}
diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.groovy
index b36c150117..2b8dd04b90 100644
--- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceHttpPortMappingsTests.groovy
@@ -44,7 +44,7 @@ public class NamespaceHttpPortMappingsTests extends BaseSpringSpec {
MockFilterChain chain
def setup() {
- request = new MockHttpServletRequest()
+ request = new MockHttpServletRequest("GET", "")
request.setMethod("GET")
response = new MockHttpServletResponse()
chain = new MockFilterChain()
diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.groovy
index fd9a1aecbf..d73f30c526 100644
--- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceRememberMeTests.groovy
@@ -371,7 +371,7 @@ public class NamespaceRememberMeTests extends BaseSpringSpec {
}
Cookie createRememberMeCookie() {
- MockHttpServletRequest request = new MockHttpServletRequest()
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)
diff --git a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy
index 1f2b8e78b3..18520a9855 100644
--- a/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/RememberMeConfigurerTests.groovy
@@ -270,7 +270,7 @@ public class RememberMeConfigurerTests extends BaseSpringSpec {
}
Cookie createRememberMeCookie() {
- MockHttpServletRequest request = new MockHttpServletRequest()
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
super.setupCsrf("CSRF_TOKEN", request, response)
diff --git a/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
index fc3e73baaa..53ea917d45 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/AbstractHttpConfigTests.groovy
@@ -67,7 +67,7 @@ abstract class AbstractHttpConfigTests extends AbstractXmlConfigTests {
}
FilterInvocation createFilterinvocation(String path, String method) {
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setMethod(method);
request.setRequestURI(null);
request.setServletPath(path);
diff --git a/config/src/test/groovy/org/springframework/security/config/http/HttpHeadersConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/HttpHeadersConfigTests.groovy
index de2a887c86..ca3c807cc7 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/HttpHeadersConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/HttpHeadersConfigTests.groovy
@@ -69,7 +69,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, defaultHeaders)
}
@@ -83,7 +83,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, defaultHeaders)
}
@@ -98,7 +98,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
def expectedHeaders = [:] << defaultHeaders
expectedHeaders['X-Frame-Options'] = 'SAMEORIGIN'
@@ -131,7 +131,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Content-Type-Options':'nosniff'])
@@ -147,7 +147,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Frame-Options':'DENY'])
@@ -163,7 +163,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Frame-Options':'DENY'])
@@ -179,7 +179,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
expect:
assertHeaders(response, ['X-Frame-Options':'SAMEORIGIN'])
@@ -228,7 +228,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-Frame-Options':'ALLOW-FROM https://example.com'])
@@ -246,7 +246,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- def request = new MockHttpServletRequest()
+ def request = new MockHttpServletRequest("GET", "")
request.setParameter("from", "https://example.com");
hf.doFilter(request, response, new MockFilterChain())
@@ -265,7 +265,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['a':'b'])
@@ -283,7 +283,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response , ['a':'b', 'c':'d'])
@@ -304,7 +304,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['abc':'def'])
}
@@ -346,7 +346,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
@@ -363,7 +363,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-XSS-Protection':'1; mode=block'])
@@ -380,7 +380,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['X-XSS-Protection':'0'])
@@ -413,7 +413,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
'Expires' : '0',
@@ -431,7 +431,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Strict-Transport-Security': 'max-age=31536000 ; includeSubDomains'])
}
@@ -447,7 +447,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
response.headerNames.empty
}
@@ -465,7 +465,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Strict-Transport-Security': 'max-age=1'])
}
@@ -515,7 +515,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="'])
}
@@ -535,7 +535,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="'])
}
@@ -555,7 +555,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
response.headerNames.empty
}
@@ -575,7 +575,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=604800 ; pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM="'])
}
@@ -595,7 +595,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins': 'max-age=5184000 ; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g="'])
}
@@ -615,7 +615,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" ; includeSubDomains'])
}
@@ -635,7 +635,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def springSecurityFilterChain = appContext.getBean(FilterChainProxy)
MockHttpServletResponse response = new MockHttpServletResponse()
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure: true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Public-Key-Pins-Report-Only': 'max-age=5184000 ; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=" ; report-uri="http://example.net/pkp-report"'])
}
@@ -657,7 +657,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
expectedHeaders.remove('Expires')
expectedHeaders.remove('Pragma')
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@@ -675,7 +675,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('X-Content-Type-Options')
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@@ -693,7 +693,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('Strict-Transport-Security')
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@@ -714,7 +714,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
MockHttpServletResponse response = new MockHttpServletResponse()
def expectedHeaders = [:] << defaultHeaders
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@@ -732,7 +732,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('X-Frame-Options')
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@@ -750,7 +750,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
def expectedHeaders = [:] << defaultHeaders
expectedHeaders.remove('X-XSS-Protection')
when:
- springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ springSecurityFilterChain.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, expectedHeaders)
}
@@ -853,7 +853,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
def expectedHeaders = [:] << defaultHeaders
expectedHeaders['Content-Security-Policy'] = 'default-src \'self\''
then:
@@ -885,7 +885,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
then:
assertHeaders(response, ['Content-Security-Policy':'default-src \'self\''])
}
@@ -913,7 +913,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(secure:true), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest(secure:true, method: "GET"), response, new MockFilterChain())
def expectedHeaders = [:] << defaultHeaders
expectedHeaders['Content-Security-Policy-Report-Only'] = 'default-src https:; report-uri https://example.com/'
then:
@@ -931,7 +931,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Referrer-Policy': 'no-referrer'])
}
@@ -947,7 +947,7 @@ class HttpHeadersConfigTests extends AbstractHttpConfigTests {
when:
def hf = getFilter(HeaderWriterFilter)
MockHttpServletResponse response = new MockHttpServletResponse()
- hf.doFilter(new MockHttpServletRequest(), response, new MockFilterChain())
+ hf.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain())
then:
assertHeaders(response, ['Referrer-Policy': 'same-origin'])
}
diff --git a/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
index 4c4bab3b99..f84677d306 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/MiscHttpConfigTests.groovy
@@ -142,7 +142,7 @@ class MiscHttpConfigTests extends AbstractHttpConfigTests {
createAppContext()
then:
Filter debugFilter = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
- MockHttpServletRequest request = new MockHttpServletRequest()
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
request.setServletPath("/unprotected");
debugFilter.doFilter(request, new MockHttpServletResponse(), new MockFilterChain());
request.setServletPath("/nomatch");
diff --git a/config/src/test/groovy/org/springframework/security/config/http/MultiHttpBlockConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/MultiHttpBlockConfigTests.groovy
index 6f06c39411..6d54e6b384 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/MultiHttpBlockConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/MultiHttpBlockConfigTests.groovy
@@ -93,7 +93,7 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
UserDetailsService uds = appContext.getBean('uds')
UserDetailsService uds2 = appContext.getBean('uds2')
when:
- MockHttpServletRequest request = new MockHttpServletRequest()
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
MockFilterChain chain = new MockFilterChain()
request.servletPath = "/first/login"
@@ -104,7 +104,7 @@ class MultiHttpBlockConfigTests extends AbstractHttpConfigTests {
verify(uds).loadUserByUsername(anyString()) || true
verifyZeroInteractions(uds2) || true
when:
- MockHttpServletRequest request2 = new MockHttpServletRequest()
+ MockHttpServletRequest request2 = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response2 = new MockHttpServletResponse()
MockFilterChain chain2 = new MockFilterChain()
request2.servletPath = "/login"
diff --git a/config/src/test/groovy/org/springframework/security/config/http/SessionManagementConfigTests.groovy b/config/src/test/groovy/org/springframework/security/config/http/SessionManagementConfigTests.groovy
index a4e2e6748c..4b7908e5e7 100644
--- a/config/src/test/groovy/org/springframework/security/config/http/SessionManagementConfigTests.groovy
+++ b/config/src/test/groovy/org/springframework/security/config/http/SessionManagementConfigTests.groovy
@@ -115,7 +115,7 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
createAppContext()
SessionRegistry registry = appContext.getBean(SessionRegistry)
registry.registerNewSession("1", new User("user","password",AuthorityUtils.createAuthorityList("ROLE_USER")))
- MockHttpServletRequest request = new MockHttpServletRequest()
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
String credentials = "user:password"
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
@@ -134,7 +134,7 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
}
}
createAppContext()
- MockHttpServletRequest request = new MockHttpServletRequest()
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "")
MockHttpServletResponse response = new MockHttpServletResponse()
String originalSessionId = request.session.id
String credentials = "user:password"
@@ -282,7 +282,7 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
mockBean(SessionAuthenticationStrategy,'ss')
createAppContext()
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.servletPath = "/login"
request.setMethod("POST");
@@ -343,15 +343,15 @@ class SessionManagementConfigTests extends AbstractHttpConfigTests {
}
};
when: "First session is established"
- seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
+ seshFilter.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain());
then: "ok"
mockResponse.redirectedUrl == null
when: "Second session is established"
- seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
+ seshFilter.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain());
then: "ok"
mockResponse.redirectedUrl == null
when: "Third session is established"
- seshFilter.doFilter(new MockHttpServletRequest(), response, new MockFilterChain());
+ seshFilter.doFilter(new MockHttpServletRequest("GET", ""), response, new MockFilterChain());
then: "Rejected"
mockResponse.redirectedUrl == "/max-exceeded";
}
diff --git a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java
index ba898c74ae..2ed1916a9e 100644
--- a/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java
+++ b/config/src/test/java/org/springframework/security/config/FilterChainProxyConfigTests.java
@@ -152,7 +152,7 @@ public class FilterChainProxyConfigTests {
}
private void doNormalOperation(FilterChainProxy filterChainProxy) throws Exception {
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setServletPath("/foo/secure/super/somefile.html");
MockHttpServletResponse response = new MockHttpServletResponse();
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
index 3cc4c10105..4adca37d33 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/builders/WebSecurityTests.java
@@ -54,7 +54,7 @@ public class WebSecurityTests {
@Before
public void setup() {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
index 3ddf21e6d6..51b0a96080 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
@@ -274,7 +274,7 @@ public class WebSecurityConfigurationTests {
public void securityExpressionHandlerWhenPermissionEvaluatorBeanThenPermissionEvaluatorUsed() throws Exception {
this.spring.register(WebSecurityExpressionHandlerPermissionEvaluatorBeanConfig.class).autowire();
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "notused");
- FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
+ FilterInvocation invocation = new FilterInvocation(new MockHttpServletRequest("GET", ""), new MockHttpServletResponse(), new MockFilterChain());
AbstractSecurityExpressionHandler handler = this.spring.getContext().getBean(AbstractSecurityExpressionHandler.class);
EvaluationContext evaluationContext = handler.createEvaluationContext(authentication, invocation);
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
index e05f6e7a01..697ddc2937 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/AuthorizeRequestsTests.java
@@ -68,7 +68,7 @@ public class AuthorizeRequestsTests {
@Before
public void setup() {
this.servletContext = spy(new MockServletContext());
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
index 3a5d338b2e..fdb6ce5e96 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityAntMatchersTests.java
@@ -51,7 +51,7 @@ public class HttpSecurityAntMatchersTests {
@Before
public void setup() {
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
index b327926ab6..30200a83c0 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityLogoutTests.java
@@ -52,7 +52,7 @@ public class HttpSecurityLogoutTests {
@Before
public void setup() {
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
index 6835425ddf..1c451a737f 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/HttpSecurityRequestMatchersTests.java
@@ -55,7 +55,7 @@ public class HttpSecurityRequestMatchersTests {
@Before
public void setup() {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
index 441a017546..6d5113c9ba 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerServlet31Tests.java
@@ -72,7 +72,7 @@ public class SessionManagementConfigurerServlet31Tests {
@Before
public void setup() {
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@@ -88,7 +88,7 @@ public class SessionManagementConfigurerServlet31Tests {
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
index 0f47ac8560..2a598af47a 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/UrlAuthorizationConfigurerTests.java
@@ -55,7 +55,7 @@ public class UrlAuthorizationConfigurerTests {
@Before
public void setup() {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();
@@ -211,4 +211,4 @@ public class UrlAuthorizationConfigurerTests {
this.context.getAutowireCapableBeanFactory().autowireBean(this);
}
-}
\ No newline at end of file
+}
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java
index 08917c1bad..ca12f7556c 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2ClientConfigurerTests.java
@@ -140,7 +140,7 @@ public class OAuth2ClientConfigurerTests {
AuthorizationRequestRepository authorizationRequestRepository =
new HttpSessionOAuth2AuthorizationRequestRepository();
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
MockHttpServletResponse response = new MockHttpServletResponse();
authorizationRequestRepository.saveAuthorizationRequest(authorizationRequest, request, response);
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
index 203143fec1..ba66ece9b4 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java
@@ -104,7 +104,7 @@ public class OAuth2LoginConfigurerTests {
@Before
public void setup() {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.response = new MockHttpServletResponse();
this.filterChain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java
index 40ff4869f4..b37cb59fdc 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java
@@ -493,7 +493,7 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
}
private MockHttpServletRequest sockjsHttpRequest(String mapping) {
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setMethod("GET");
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,
"/289/tpyx6mde/websocket");
diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java
index f35139dd99..8b5ad38224 100644
--- a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java
+++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsJcTests.java
@@ -65,7 +65,7 @@ public class GrantedAuthorityDefaultsJcTests {
public void setup() {
setup("USER");
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
request.setMethod("GET");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java
index c36341ab50..6eac7b9254 100644
--- a/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java
+++ b/config/src/test/java/org/springframework/security/config/core/GrantedAuthorityDefaultsXmlTests.java
@@ -58,7 +58,7 @@ public class GrantedAuthorityDefaultsXmlTests {
public void setup() {
setup("USER");
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
request.setMethod("GET");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java
index 7b8e1ccd9d..23a0691fb9 100644
--- a/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/FilterSecurityMetadataSourceBeanDefinitionParserTests.java
@@ -123,7 +123,7 @@ public class FilterSecurityMetadataSourceBeanDefinitionParserTests {
}
private FilterInvocation createFilterInvocation(String path, String method) {
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setRequestURI(null);
request.setMethod(method);
diff --git a/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java b/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java
index da546e69e1..449320ba5c 100644
--- a/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/NamespaceHttpBasicTests.java
@@ -52,7 +52,7 @@ public class NamespaceHttpBasicTests {
@Before
public void setup() {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setMethod("GET");
this.response = new MockHttpServletResponse();
this.chain = new MockFilterChain();
diff --git a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java
index 19da353fbd..a1bf8cea93 100644
--- a/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java
+++ b/config/src/test/java/org/springframework/security/config/http/SessionManagementConfigServlet31Tests.java
@@ -73,7 +73,7 @@ public class SessionManagementConfigServlet31Tests {
@Before
public void setup() {
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
}
@@ -89,7 +89,7 @@ public class SessionManagementConfigServlet31Tests {
public void changeSessionIdDefaultsInServlet31Plus() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
@@ -112,7 +112,7 @@ public class SessionManagementConfigServlet31Tests {
public void changeSessionId() throws Exception {
spy(ReflectionUtils.class);
Method method = mock(Method.class);
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.getSession();
request.setServletPath("/login");
request.setMethod("POST");
diff --git a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java
index beda71be97..3d0bfa7edf 100644
--- a/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java
+++ b/config/src/test/java/org/springframework/security/config/http/customconfigurer/CustomHttpSecurityConfigurerTests.java
@@ -55,7 +55,7 @@ public class CustomHttpSecurityConfigurerTests {
@Before
public void setup() {
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
response = new MockHttpServletResponse();
chain = new MockFilterChain();
request.setMethod("GET");
diff --git a/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-AutoConfig.xml b/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-AutoConfig.xml
index 44959cf8d9..644f4a8d74 100644
--- a/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-AutoConfig.xml
+++ b/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-AutoConfig.xml
@@ -18,10 +18,15 @@
+
+
+
diff --git a/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml b/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml
index 3a09d6e370..001214c123 100644
--- a/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml
+++ b/config/src/test/resources/org/springframework/security/config/http/CsrfConfigTests-CsrfEnabled.xml
@@ -18,13 +18,18 @@
+
+
+
diff --git a/docs/manual/src/docs/asciidoc/_includes/web/security-filter-chain.adoc b/docs/manual/src/docs/asciidoc/_includes/web/security-filter-chain.adoc
index 5c3d68c874..4333b18263 100644
--- a/docs/manual/src/docs/asciidoc/_includes/web/security-filter-chain.adoc
+++ b/docs/manual/src/docs/asciidoc/_includes/web/security-filter-chain.adoc
@@ -179,6 +179,45 @@ public StrictHttpFirewall httpFirewall() {
}
----
+The `StrictHttpFirewall` provides a whitelist of valid HTTP methods that are allowed to protect against https://www.owasp.org/index.php/Cross_Site_Tracing[Cross Site Tracing (XST)] and https://www.owasp.org/index.php/Test_HTTP_Methods_(OTG-CONFIG-006)[HTTP Verb Tampering].
+The default valid methods are "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", and "PUT".
+If your application needs to modify the valid methods, you can configure a custom `StrictHttpFirewall` bean.
+For example, the following will only allow HTTP "GET" and "POST" methods:
+
+
+[source,xml]
+----
+
+
+
+----
+
+The same thing can be achieved with Java Configuration by exposing a `StrictHttpFirewall` bean.
+
+[source,java]
+----
+@Bean
+public StrictHttpFirewall httpFirewall() {
+ StrictHttpFirewall firewall = new StrictHttpFirewall();
+ firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST"));
+ return firewall;
+}
+----
+
+[TIP]
+====
+If you are using `new MockHttpServletRequest()` it currently creates an HTTP method as an empty String "".
+This is an invalid HTTP method and will be rejected by Spring Security.
+You can resolve this by replacing it with `new MockHttpServletRequest("GET", "")`.
+See https://jira.spring.io/browse/SPR-16851[SPR_16851] for an issue requesting to improve this.
+====
+
+If you must allow any HTTP method (not recommended), you can use `StrictHttpFirewall.setUnsafeAllowAnyHttpMethod(true)`.
+This will disable validation of the HTTP method entirely.
+
+
=== Use with other Filter-Based Frameworks
If you're using some other framework that is also filter-based, then you need to make sure that the Spring Security filters come first.
This enables the `SecurityContextHolder` to be populated in time for use by the other filters.
diff --git a/web/src/main/java/org/springframework/security/web/FilterChainProxy.java b/web/src/main/java/org/springframework/security/web/FilterChainProxy.java
index 040a263bcd..959f9b0d49 100644
--- a/web/src/main/java/org/springframework/security/web/FilterChainProxy.java
+++ b/web/src/main/java/org/springframework/security/web/FilterChainProxy.java
@@ -238,7 +238,7 @@ public class FilterChainProxy extends GenericFilterBean {
* @return matching filter list
*/
public List getFilters(String url) {
- return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, null)
+ return getFilters(firewall.getFirewalledRequest((new FilterInvocation(url, "GET")
.getRequest())));
}
diff --git a/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java b/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java
index ddfc2e8faa..03eaeeec16 100644
--- a/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java
+++ b/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java
@@ -16,6 +16,8 @@
package org.springframework.security.web.firewall;
+import org.springframework.http.HttpMethod;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
@@ -35,6 +37,11 @@ import java.util.Set;
*
*
* -
+ * Rejects HTTP methods that are not allowed. This specified to block
+ * HTTP Verb tampering and XST attacks.
+ * See {@link #setAllowedHttpMethods(Collection)}
+ *
+ * -
* Rejects URLs that are not normalized to avoid bypassing security constraints. There is
* no way to disable this as it is considered extremely risky to disable this constraint.
* A few options to allow this behavior is to normalize the request prior to the firewall
@@ -66,6 +73,11 @@ import java.util.Set;
* @since 4.2.4
*/
public class StrictHttpFirewall implements HttpFirewall {
+ /**
+ * Used to specify to {@link #setAllowedHttpMethods(Collection)} that any HTTP method should be allowed.
+ */
+ private static final Set ALLOW_ANY_HTTP_METHOD = Collections.unmodifiableSet(Collections.emptySet());
+
private static final String ENCODED_PERCENT = "%25";
private static final String PERCENT = "%";
@@ -82,6 +94,8 @@ public class StrictHttpFirewall implements HttpFirewall {
private Set decodedUrlBlacklist = new HashSet();
+ private Set allowedHttpMethods = createDefaultAllowedHttpMethods();
+
public StrictHttpFirewall() {
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
@@ -92,6 +106,39 @@ public class StrictHttpFirewall implements HttpFirewall {
this.decodedUrlBlacklist.add(PERCENT);
}
+ /**
+ * Sets if any HTTP method is allowed. If this set to true, then no validation on the HTTP method will be performed.
+ * This can open the application up to
+ * HTTP Verb tampering and XST attacks
+ * @param unsafeAllowAnyHttpMethod if true, disables HTTP method validation, else resets back to the defaults. Default is false.
+ * @see #setAllowedHttpMethods(Collection)
+ * @since 5.1
+ */
+ public void setUnsafeAllowAnyHttpMethod(boolean unsafeAllowAnyHttpMethod) {
+ this.allowedHttpMethods = unsafeAllowAnyHttpMethod ? ALLOW_ANY_HTTP_METHOD : createDefaultAllowedHttpMethods();
+ }
+
+ /**
+ *
+ * Determines which HTTP methods should be allowed. The default is to allow "DELETE", "GET", "HEAD", "OPTIONS",
+ * "PATCH", "POST", and "PUT".
+ *
+ *
+ * @param allowedHttpMethods the case-sensitive collection of HTTP methods that are allowed.
+ * @see #setUnsafeAllowAnyHttpMethod(boolean)
+ * @since 5.1
+ */
+ public void setAllowedHttpMethods(Collection allowedHttpMethods) {
+ if (allowedHttpMethods == null) {
+ throw new IllegalArgumentException("allowedHttpMethods cannot be null");
+ }
+ if (allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {
+ this.allowedHttpMethods = ALLOW_ANY_HTTP_METHOD;
+ } else {
+ this.allowedHttpMethods = new HashSet<>(allowedHttpMethods);
+ }
+ }
+
/**
*
* Determines if semicolon is allowed in the URL (i.e. matrix variables). The default
@@ -242,6 +289,7 @@ public class StrictHttpFirewall implements HttpFirewall {
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
+ rejectForbiddenHttpMethod(request);
rejectedBlacklistedUrls(request);
if (!isNormalized(request)) {
@@ -259,6 +307,18 @@ public class StrictHttpFirewall implements HttpFirewall {
};
}
+ private void rejectForbiddenHttpMethod(HttpServletRequest request) {
+ if (this.allowedHttpMethods == ALLOW_ANY_HTTP_METHOD) {
+ return;
+ }
+ if (!this.allowedHttpMethods.contains(request.getMethod())) {
+ throw new RequestRejectedException("The request was rejected because the HTTP method \"" +
+ request.getMethod() +
+ "\" was not included within the whitelist " +
+ this.allowedHttpMethods);
+ }
+ }
+
private void rejectedBlacklistedUrls(HttpServletRequest request) {
for (String forbidden : this.encodedUrlBlacklist) {
if (encodedUrlContains(request, forbidden)) {
@@ -277,6 +337,18 @@ public class StrictHttpFirewall implements HttpFirewall {
return new FirewalledResponse(response);
}
+ private static Set createDefaultAllowedHttpMethods() {
+ Set result = new HashSet<>();
+ result.add(HttpMethod.DELETE.name());
+ result.add(HttpMethod.GET.name());
+ result.add(HttpMethod.HEAD.name());
+ result.add(HttpMethod.OPTIONS.name());
+ result.add(HttpMethod.PATCH.name());
+ result.add(HttpMethod.POST.name());
+ result.add(HttpMethod.PUT.name());
+ return result;
+ }
+
private static boolean isNormalized(HttpServletRequest request) {
if (!isNormalized(request.getRequestURI())) {
return false;
diff --git a/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java b/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java
index 576fda3f75..6273849424 100644
--- a/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java
+++ b/web/src/test/java/org/springframework/security/web/FilterChainProxyTests.java
@@ -69,7 +69,7 @@ public class FilterChainProxyTests {
fcp = new FilterChainProxy(new DefaultSecurityFilterChain(matcher,
Arrays.asList(filter)));
fcp.setFilterChainValidator(mock(FilterChainProxy.FilterChainValidator.class));
- request = new MockHttpServletRequest();
+ request = new MockHttpServletRequest("GET", "");
request.setServletPath("/path");
response = new MockHttpServletResponse();
chain = mock(FilterChain.class);
diff --git a/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java b/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java
index 5d2e57d3e7..27e2c0c380 100644
--- a/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java
+++ b/web/src/test/java/org/springframework/security/web/firewall/StrictHttpFirewallTests.java
@@ -16,11 +16,17 @@
package org.springframework.security.web.firewall;
-import org.junit.Test;
-import org.springframework.mock.web.MockHttpServletRequest;
-
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.springframework.http.HttpMethod;
+import org.springframework.mock.web.MockHttpServletRequest;
+
/**
* @author Rob Winch
*/
@@ -31,12 +37,61 @@ public class StrictHttpFirewallTests {
private StrictHttpFirewall firewall = new StrictHttpFirewall();
- private MockHttpServletRequest request = new MockHttpServletRequest();
+ private MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
+
+ @Test
+ public void getFirewalledRequestWhenInvalidMethodThenThrowsRequestRejectedException() {
+ this.request.setMethod("INVALID");
+ assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
+ .isInstanceOf(RequestRejectedException.class);
+ }
+
+ // blocks XST attacks
+ @Test
+ public void getFirewalledRequestWhenTraceMethodThenThrowsRequestRejectedException() {
+ this.request.setMethod(HttpMethod.TRACE.name());
+ assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
+ .isInstanceOf(RequestRejectedException.class);
+ }
+
+ @Test
+ // blocks XST attack if request is forwarded to a Microsoft IIS web server
+ public void getFirewalledRequestWhenTrackMethodThenThrowsRequestRejectedException() {
+ this.request.setMethod("TRACK");
+ assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
+ .isInstanceOf(RequestRejectedException.class);
+ }
+
+ @Test
+ // HTTP methods are case sensitive
+ public void getFirewalledRequestWhenLowercaseGetThenThrowsRequestRejectedException() {
+ this.request.setMethod("get");
+ assertThatThrownBy(() -> this.firewall.getFirewalledRequest(this.request))
+ .isInstanceOf(RequestRejectedException.class);
+ }
+
+ @Test
+ public void getFirewalledRequestWhenAllowedThenNoException() {
+ List allowedMethods = Arrays.asList("DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT");
+ for (String allowedMethod : allowedMethods) {
+ this.request = new MockHttpServletRequest(allowedMethod, "");
+ assertThatCode(() -> this.firewall.getFirewalledRequest(this.request))
+ .doesNotThrowAnyException();
+ }
+ }
+
+ @Test
+ public void getFirewalledRequestWhenInvalidMethodAndAnyMethodThenNoException() {
+ this.firewall.setUnsafeAllowAnyHttpMethod(true);
+ this.request.setMethod("INVALID");
+ assertThatCode(() -> this.firewall.getFirewalledRequest(this.request))
+ .doesNotThrowAnyException();
+ }
@Test
public void getFirewalledRequestWhenRequestURINotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setRequestURI(path);
try {
this.firewall.getFirewalledRequest(this.request);
@@ -49,7 +104,7 @@ public class StrictHttpFirewallTests {
@Test
public void getFirewalledRequestWhenContextPathNotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setContextPath(path);
try {
this.firewall.getFirewalledRequest(this.request);
@@ -62,7 +117,7 @@ public class StrictHttpFirewallTests {
@Test
public void getFirewalledRequestWhenServletPathNotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setServletPath(path);
try {
this.firewall.getFirewalledRequest(this.request);
@@ -75,7 +130,7 @@ public class StrictHttpFirewallTests {
@Test
public void getFirewalledRequestWhenPathInfoNotNormalizedThenThrowsRequestRejectedException() throws Exception {
for (String path : this.unnormalizedPaths) {
- this.request = new MockHttpServletRequest();
+ this.request = new MockHttpServletRequest("GET", "");
this.request.setPathInfo(path);
try {
this.firewall.getFirewalledRequest(this.request);
@@ -352,7 +407,7 @@ public class StrictHttpFirewallTests {
public void getFirewalledRequestWhenAllowUrlEncodedSlashAndLowercaseEncodedPathThenNoException() {
this.firewall.setAllowUrlEncodedSlash(true);
this.firewall.setAllowSemicolon(true);
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setRequestURI("/context-root/a/b;%2f1/c");
request.setContextPath("/context-root");
request.setServletPath("");
@@ -365,7 +420,7 @@ public class StrictHttpFirewallTests {
public void getFirewalledRequestWhenAllowUrlEncodedSlashAndUppercaseEncodedPathThenNoException() {
this.firewall.setAllowUrlEncodedSlash(true);
this.firewall.setAllowSemicolon(true);
- MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
request.setRequestURI("/context-root/a/b;%2F1/c");
request.setContextPath("/context-root");
request.setServletPath("");