diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java index 00045baba65..ffcedad60bb 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java @@ -142,22 +142,12 @@ private T getBeanOrNull(Class type) { return null; } } + @SuppressWarnings("unchecked") private RequestMatcher createDefaultSavedRequestMatcher(H http) { - ContentNegotiationStrategy contentNegotiationStrategy = http - .getSharedObject(ContentNegotiationStrategy.class); - if (contentNegotiationStrategy == null) { - contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); - } - RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher( "/**/favicon.*")); - MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher( - contentNegotiationStrategy, MediaType.APPLICATION_JSON); - jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); - RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest); - RequestMatcher notXRequestedWith = new NegatedRequestMatcher( new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest")); @@ -169,9 +159,21 @@ private RequestMatcher createDefaultSavedRequestMatcher(H http) { matchers.add(0, getRequests); } matchers.add(notFavIcon); - matchers.add(notJson); + matchers.add(notMatchingMediaType(http, MediaType.APPLICATION_JSON)); matchers.add(notXRequestedWith); + matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA)); return new AndRequestMatcher(matchers); } + + private RequestMatcher notMatchingMediaType(H http, MediaType mediaType) { + ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class); + if (contentNegotiationStrategy == null) { + contentNegotiationStrategy = new HeaderContentNegotiationStrategy(); + } + + MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, mediaType); + jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL)); + return new NegatedRequestMatcher(jsonRequest); + } } diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java index 683a4951c2c..a193f1c887a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java @@ -26,6 +26,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpSession; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -45,6 +46,7 @@ import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; /** @@ -262,6 +264,21 @@ public void getWhenRequestCacheIsDisabledThenExceptionTranslationFilterDoesNotSt .andExpect(redirectedUrl("/")); } + // SEC-7060 + @Test + public void postWhenRequestIsMultipartThenPostAuthenticationRedirectsToRoot() throws Exception { + this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire(); + + MockMultipartFile aFile = new MockMultipartFile("aFile", "A_FILE".getBytes()); + + MockHttpSession session = (MockHttpSession) + this.mvc.perform(multipart("/upload") + .file(aFile)) + .andReturn().getRequest().getSession(); + + this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/")); + } + @EnableWebSecurity static class RequestCacheDisabledConfig extends WebSecurityConfigurerAdapter { @Override