Skip to content

Commit 71444ff

Browse files
committed
RequestCache ignores multipart requests
Fixes gh-7060
2 parents 9735a71 + 08ea234 commit 71444ff

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java

+14-12
Original file line numberDiff line numberDiff line change
@@ -142,22 +142,12 @@ private <T> T getBeanOrNull(Class<T> type) {
142142
return null;
143143
}
144144
}
145+
145146
@SuppressWarnings("unchecked")
146147
private RequestMatcher createDefaultSavedRequestMatcher(H http) {
147-
ContentNegotiationStrategy contentNegotiationStrategy = http
148-
.getSharedObject(ContentNegotiationStrategy.class);
149-
if (contentNegotiationStrategy == null) {
150-
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
151-
}
152-
153148
RequestMatcher notFavIcon = new NegatedRequestMatcher(new AntPathRequestMatcher(
154149
"/**/favicon.*"));
155150

156-
MediaTypeRequestMatcher jsonRequest = new MediaTypeRequestMatcher(
157-
contentNegotiationStrategy, MediaType.APPLICATION_JSON);
158-
jsonRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
159-
RequestMatcher notJson = new NegatedRequestMatcher(jsonRequest);
160-
161151
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
162152
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
163153

@@ -169,9 +159,21 @@ private RequestMatcher createDefaultSavedRequestMatcher(H http) {
169159
matchers.add(0, getRequests);
170160
}
171161
matchers.add(notFavIcon);
172-
matchers.add(notJson);
162+
matchers.add(notMatchingMediaType(http, MediaType.APPLICATION_JSON));
173163
matchers.add(notXRequestedWith);
164+
matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA));
174165

175166
return new AndRequestMatcher(matchers);
176167
}
168+
169+
private RequestMatcher notMatchingMediaType(H http, MediaType mediaType) {
170+
ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
171+
if (contentNegotiationStrategy == null) {
172+
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
173+
}
174+
175+
MediaTypeRequestMatcher mediaRequest = new MediaTypeRequestMatcher(contentNegotiationStrategy, mediaType);
176+
mediaRequest.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
177+
return new NegatedRequestMatcher(mediaRequest);
178+
}
177179
}

config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.http.HttpHeaders;
2727
import org.springframework.http.MediaType;
2828
import org.springframework.mock.web.MockHttpSession;
29+
import org.springframework.mock.web.MockMultipartFile;
2930
import org.springframework.security.config.annotation.ObjectPostProcessor;
3031
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3132
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -47,6 +48,7 @@
4748
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
4849
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
4950
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
51+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
5052
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
5153

5254
/**
@@ -264,6 +266,21 @@ public void getWhenRequestCacheIsDisabledThenExceptionTranslationFilterDoesNotSt
264266
.andExpect(redirectedUrl("/"));
265267
}
266268

269+
// SEC-7060
270+
@Test
271+
public void postWhenRequestIsMultipartThenPostAuthenticationRedirectsToRoot() throws Exception {
272+
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
273+
274+
MockMultipartFile aFile = new MockMultipartFile("aFile", "A_FILE".getBytes());
275+
276+
MockHttpSession session = (MockHttpSession)
277+
this.mvc.perform(multipart("/upload")
278+
.file(aFile))
279+
.andReturn().getRequest().getSession();
280+
281+
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
282+
}
283+
267284
@EnableWebSecurity
268285
static class RequestCacheDisabledConfig extends WebSecurityConfigurerAdapter {
269286
@Override

0 commit comments

Comments
 (0)