Skip to content

Commit 5a2e93e

Browse files
Fixed NPE for ill-constructed HTTP requests with non-standard HTTP method in CsrfWebFilter
1 parent a783fbc commit 5a2e93e

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

web/src/main/java/org/springframework/security/web/server/csrf/CsrfWebFilter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -60,6 +60,7 @@
6060
* </p>
6161
*
6262
* @author Rob Winch
63+
* @author Parikshit Dutta
6364
* @since 5.0
6465
*/
6566
public class CsrfWebFilter implements WebFilter {
@@ -187,7 +188,7 @@ private static class DefaultRequireCsrfProtectionMatcher implements ServerWebExc
187188
@Override
188189
public Mono<MatchResult> matches(ServerWebExchange exchange) {
189190
return Mono.just(exchange.getRequest())
190-
.map(r -> r.getMethod())
191+
.flatMap(r -> Mono.justOrEmpty(r.getMethod()))
191192
.filter(m -> ALLOWED_METHODS.contains(m))
192193
.flatMap(m -> MatchResult.notMatch())
193194
.switchIfEmpty(MatchResult.match());

web/src/test/java/org/springframework/security/web/server/csrf/CsrfWebFilterTests.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
2020
import org.junit.runner.RunWith;
2121
import org.mockito.Mock;
2222
import org.mockito.junit.MockitoJUnitRunner;
23+
24+
import org.springframework.http.HttpMethod;
2325
import org.springframework.http.HttpStatus;
2426
import org.springframework.http.MediaType;
2527
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
@@ -40,11 +42,14 @@
4042
import static org.mockito.Mockito.mock;
4143
import static org.mockito.Mockito.verifyZeroInteractions;
4244
import static org.mockito.Mockito.when;
45+
import static org.mockito.Mockito.verify;
46+
import static org.mockito.Mockito.spy;
4347
import static org.springframework.mock.web.server.MockServerWebExchange.from;
4448
import static org.springframework.web.reactive.function.BodyInserters.fromMultipartData;
4549

4650
/**
4751
* @author Rob Winch
52+
* @author Parikshit Dutta
4853
* @since 5.0
4954
*/
5055
@RunWith(MockitoJUnitRunner.class)
@@ -183,6 +188,18 @@ public void filterWhenPostAndEstablishedCsrfTokenAndHeaderValidTokenThenContinue
183188
chainResult.assertWasSubscribed();
184189
}
185190

191+
@Test
192+
public void matchesRequireCSRFProtectionWhenNonStandardHTTPMethodIsUsed() {
193+
final String NON_STANDARD_HTTP_METHOD = "non-standard-http-method";
194+
MockServerWebExchange nonStandardHttpRequest = from(MockServerHttpRequest.method(HttpMethod.resolve(NON_STANDARD_HTTP_METHOD), "/"));
195+
196+
ServerWebExchangeMatcher serverWebExchangeMatcher = spy(CsrfWebFilter.DEFAULT_CSRF_MATCHER);
197+
serverWebExchangeMatcher.matches(nonStandardHttpRequest);
198+
199+
verify(serverWebExchangeMatcher).matches(nonStandardHttpRequest);
200+
assertThat(serverWebExchangeMatcher.matches(nonStandardHttpRequest).block().isMatch()).isTrue();
201+
}
202+
186203
@Test
187204
public void doFilterWhenSkipExchangeInvokedThenSkips() {
188205
PublisherProbe<Void> chainResult = PublisherProbe.empty();

0 commit comments

Comments
 (0)