1
0
mirror of synced 2026-08-05 17:57:15 +00:00

Compare commits

...

15 Commits

Author SHA1 Message Date
Eleftheria Stein 37568780a1 Release 5.1.11.RELEASE 2020-06-03 17:48:40 -04:00
Josh Cummings d80b1865a5 Polish setAllowedHostnames
Added JavaDoc to method, including @since attribute

Issue gh-4310
2020-06-03 08:54:06 -06:00
Eddú Meléndez 52c80c78e5 Add support for allowedHostnames in StrictHttpFirewall
Introduce a new method `setAllowedHostnames` which perform the validation
against untrusted hostnames.

Fixes gh-4310
2020-06-03 08:53:59 -06:00
Eleftheria Stein ded83cc1b3 Update to jaxb-impl 2.3.3
Fixes gh-8634
2020-06-02 18:45:14 -04:00
Eleftheria Stein 7a1833c1df Update to okhttp 3.12.12
Fixes gh-8635
2020-06-02 18:45:14 -04:00
Eleftheria Stein e6630ea0f1 Update to mockwebserver 3.12.12
Fixes gh-8633
2020-06-02 18:45:14 -04:00
Eleftheria Stein 2400e8fde2 Update to Spring Boot 2.1.14.RELEASE
Fixes gh-8632
2020-06-02 18:45:14 -04:00
justmehyp f05d70a4a5 Remove unused field 'digester' in Md4PasswordEncoder
`private Digester digester;`  defined in Md4PasswordEncoder is never used. So remove it.

Closes gh-8553
2020-05-21 11:21:40 -05:00
Maksim Vinogradov 8bb4e72aff Prevent StackOverflowError for AccessControlEntryImpl.hashCode
Getting StackOverflowError when invoke AclImpl.hashCode because of
cross-references between AclImpl and AccessControlEntryImpl

Remove from AccessControlEntryImpl.hashCode method invocation of
acl.hashCode

fixes gh-5401
2020-05-21 10:08:56 -05:00
Rob Winch f58a262eb4 Revert "Create the CSRF token on the bounded elactic scheduler"
Reactor did not add bounded elastic until a later version.

This reverts commit c0154f2315.
2020-05-18 11:10:41 -05:00
cbornet c0154f2315 Create the CSRF token on the bounded elactic scheduler
The CSRF token is created with a call to UUID.randomUUID which is blocking.
This change ensures this blocking call is done on the bounded elastic scheduler which supports blocking calls.

Fixes gh-8128
2020-05-18 11:07:08 -05:00
Artyom Tarynin cea2b556d6 Update AntPathRequestMatcher.java
Fixes gh-8512
2020-05-14 10:36:30 -04:00
Dávid Kovács faa02e8bc0 Document NoOpPasswordEncoder will not be removed
This commit adds extension to deprecation notice.

Fixes gh-8506
2020-05-13 12:56:22 -05:00
Rob Winch d9f57492d4 Fix non-standard HTTP method for CsrfWebFilter
Closes gh-8452
2020-05-12 13:21:22 -05:00
Eleftheria Stein b007fdc333 Next development version 2020-05-06 16:27:44 -04:00
12 changed files with 118 additions and 31 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -131,10 +131,9 @@ public class AccessControlEntryImpl implements AccessControlEntry,
@Override @Override
public int hashCode() { public int hashCode() {
int result = this.acl.hashCode(); int result = this.permission.hashCode();
result = 31 * result + this.permission.hashCode();
result = 31 * result + (this.id != null ? this.id.hashCode() : 0); result = 31 * result + (this.id != null ? this.id.hashCode() : 0);
result = 31 * result + this.sid.hashCode(); result = 31 * result + (this.sid.hashCode());
result = 31 * result + (this.auditFailure ? 1 : 0); result = 31 * result + (this.auditFailure ? 1 : 0);
result = 31 * result + (this.auditSuccess ? 1 : 0); result = 31 * result + (this.auditSuccess ? 1 : 0);
result = 31 * result + (this.granting ? 1 : 0); result = 31 * result + (this.granting ? 1 : 0);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -560,6 +560,25 @@ public class AclImplTests {
childAcl.setParent(changeParentAcl); childAcl.setParent(changeParentAcl);
} }
@Test
public void hashCodeWithoutStackOverFlow() throws Exception {
//given
Sid sid = new PrincipalSid("pSid");
ObjectIdentity oid = new ObjectIdentityImpl("type", 1);
AclAuthorizationStrategy authStrategy = new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("role"));
PermissionGrantingStrategy grantingStrategy = new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
AclImpl acl = new AclImpl(oid, 1L, authStrategy, grantingStrategy, null, null, false, sid);
AccessControlEntryImpl ace = new AccessControlEntryImpl(1L, acl, sid, BasePermission.READ, true, true, true);
Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
fieldAces.setAccessible(true);
List<AccessControlEntryImpl> aces = (List<AccessControlEntryImpl>) fieldAces.get(acl);
aces.add(ace);
//when - then none StackOverFlowError been raised
ace.hashCode();
}
// ~ Inner Classes // ~ Inner Classes
// ================================================================================================== // ==================================================================================================
@@ -83,8 +83,6 @@ public class Md4PasswordEncoder implements PasswordEncoder {
private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator(); private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
private boolean encodeHashAsBase64; private boolean encodeHashAsBase64;
private Digester digester;
public void setEncodeHashAsBase64(boolean encodeHashAsBase64) { public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
this.encodeHashAsBase64 = encodeHashAsBase64; this.encodeHashAsBase64 = encodeHashAsBase64;
@@ -26,7 +26,8 @@ package org.springframework.security.crypto.password;
* @deprecated This PasswordEncoder is not secure. Instead use an * @deprecated This PasswordEncoder is not secure. Instead use an
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or * adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports * SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
* password upgrades. * password upgrades. There are no plans to remove this support. It is deprecated to indicate that
* this is a legacy implementation and using it is considered insecure.
*/ */
@Deprecated @Deprecated
public final class NoOpPasswordEncoder implements PasswordEncoder { public final class NoOpPasswordEncoder implements PasswordEncoder {
+2 -2
View File
@@ -1,3 +1,3 @@
gaeVersion=1.9.80 gaeVersion=1.9.80
springBootVersion=2.1.13.RELEASE springBootVersion=2.1.14.RELEASE
version=5.1.10.RELEASE version=5.1.11.RELEASE
+3 -3
View File
@@ -18,7 +18,7 @@ dependencyManagement {
} }
dependencies { dependencies {
dependency 'cglib:cglib-nodep:3.2.12' dependency 'cglib:cglib-nodep:3.2.12'
dependency 'com.squareup.okhttp3:mockwebserver:3.12.10' dependency 'com.squareup.okhttp3:mockwebserver:3.12.12'
dependency 'opensymphony:sitemesh:2.4.2' dependency 'opensymphony:sitemesh:2.4.2'
dependency 'org.gebish:geb-spock:0.10.0' dependency 'org.gebish:geb-spock:0.10.0'
dependency 'org.jasig.cas:cas-server-webapp:4.2.7' dependency 'org.jasig.cas:cas-server-webapp:4.2.7'
@@ -56,10 +56,10 @@ dependencyManagement {
dependency 'com.nimbusds:lang-tag:1.4.3' dependency 'com.nimbusds:lang-tag:1.4.3'
dependency 'com.nimbusds:nimbus-jose-jwt:6.0.2' dependency 'com.nimbusds:nimbus-jose-jwt:6.0.2'
dependency 'com.nimbusds:oauth2-oidc-sdk:6.0' dependency 'com.nimbusds:oauth2-oidc-sdk:6.0'
dependency 'com.squareup.okhttp3:okhttp:3.12.10' dependency 'com.squareup.okhttp3:okhttp:3.12.12'
dependency 'com.squareup.okio:okio:1.13.0' dependency 'com.squareup.okio:okio:1.13.0'
dependency 'com.sun.xml.bind:jaxb-core:2.3.0.1' dependency 'com.sun.xml.bind:jaxb-core:2.3.0.1'
dependency 'com.sun.xml.bind:jaxb-impl:2.3.2' dependency 'com.sun.xml.bind:jaxb-impl:2.3.3'
dependency 'com.unboundid:unboundid-ldapsdk:4.0.14' dependency 'com.unboundid:unboundid-ldapsdk:4.0.14'
dependency 'com.vaadin.external.google:android-json:0.0.20131108.vaadin1' dependency 'com.vaadin.external.google:android-json:0.0.20131108.vaadin1'
dependency 'commons-cli:commons-cli:1.4' dependency 'commons-cli:commons-cli:1.4'
@@ -228,10 +228,15 @@ class DummyRequest extends HttpServletRequestWrapper {
public void setQueryString(String queryString) { public void setQueryString(String queryString) {
this.queryString = queryString; this.queryString = queryString;
} }
@Override
public String getServerName() {
return null;
}
} }
final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler { final class UnsupportedOperationExceptionInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
throw new UnsupportedOperationException(method + " is not supported"); throw new UnsupportedOperationException(method + " is not supported");
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,16 +16,17 @@
package org.springframework.security.web.firewall; 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; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpMethod;
/** /**
* <p> * <p>
@@ -66,10 +67,15 @@ import java.util.Set;
* Rejects URLs that contain a URL encoded percent. See * Rejects URLs that contain a URL encoded percent. See
* {@link #setAllowUrlEncodedPercent(boolean)} * {@link #setAllowUrlEncodedPercent(boolean)}
* </li> * </li>
* <li>
* Rejects hosts that are not allowed. See
* {@link #setAllowedHostnames(Predicate)}
* </li>
* </ul> * </ul>
* *
* @see DefaultHttpFirewall * @see DefaultHttpFirewall
* @author Rob Winch * @author Rob Winch
* @author Eddú Meléndez
* @since 4.2.4 * @since 4.2.4
*/ */
public class StrictHttpFirewall implements HttpFirewall { public class StrictHttpFirewall implements HttpFirewall {
@@ -96,6 +102,8 @@ public class StrictHttpFirewall implements HttpFirewall {
private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods(); private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods();
private Predicate<String> allowedHostnames = hostname -> true;
public StrictHttpFirewall() { public StrictHttpFirewall() {
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON); urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH); urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
@@ -277,6 +285,21 @@ public class StrictHttpFirewall implements HttpFirewall {
} }
} }
/**
* <p>
* Determines which hostnames should be allowed. The default is to allow any hostname.
* </p>
*
* @param allowedHostnames the predicate for testing hostnames
* @since 5.1.11
*/
public void setAllowedHostnames(Predicate<String> allowedHostnames) {
if (allowedHostnames == null) {
throw new IllegalArgumentException("allowedHostnames cannot be null");
}
this.allowedHostnames = allowedHostnames;
}
private void urlBlacklistsAddAll(Collection<String> values) { private void urlBlacklistsAddAll(Collection<String> values) {
this.encodedUrlBlacklist.addAll(values); this.encodedUrlBlacklist.addAll(values);
this.decodedUrlBlacklist.addAll(values); this.decodedUrlBlacklist.addAll(values);
@@ -291,6 +314,7 @@ public class StrictHttpFirewall implements HttpFirewall {
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
rejectForbiddenHttpMethod(request); rejectForbiddenHttpMethod(request);
rejectedBlacklistedUrls(request); rejectedBlacklistedUrls(request);
rejectedUntrustedHosts(request);
if (!isNormalized(request)) { if (!isNormalized(request)) {
throw new RequestRejectedException("The request was rejected because the URL was not normalized."); throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
@@ -332,6 +356,13 @@ public class StrictHttpFirewall implements HttpFirewall {
} }
} }
private void rejectedUntrustedHosts(HttpServletRequest request) {
String serverName = request.getServerName();
if (serverName != null && !this.allowedHostnames.test(serverName)) {
throw new RequestRejectedException("The request was rejected because the domain " + serverName + " is untrusted.");
}
}
@Override @Override
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) { public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
return new FirewalledResponse(response); return new FirewalledResponse(response);
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@ import org.springframework.web.server.WebFilterChain;
* </p> * </p>
* *
* @author Rob Winch * @author Rob Winch
* @author Parikshit Dutta
* @since 5.0 * @since 5.0
*/ */
public class CsrfWebFilter implements WebFilter { public class CsrfWebFilter implements WebFilter {
@@ -136,7 +137,7 @@ public class CsrfWebFilter implements WebFilter {
@Override @Override
public Mono<MatchResult> matches(ServerWebExchange exchange) { public Mono<MatchResult> matches(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest()) return Mono.just(exchange.getRequest())
.map(r -> r.getMethod()) .flatMap(r -> Mono.justOrEmpty(r.getMethod()))
.filter(m -> ALLOWED_METHODS.contains(m)) .filter(m -> ALLOWED_METHODS.contains(m))
.flatMap(m -> MatchResult.notMatch()) .flatMap(m -> MatchResult.notMatch())
.switchIfEmpty(MatchResult.match()); .switchIfEmpty(MatchResult.match());
@@ -67,7 +67,7 @@ public final class AntPathRequestMatcher
/** /**
* Creates a matcher with the specific pattern which will match all HTTP methods in a * Creates a matcher with the specific pattern which will match all HTTP methods in a
* case insensitive manner. * case sensitive manner.
* *
* @param pattern the ant pattern to use for matching * @param pattern the ant pattern to use for matching
*/ */
@@ -76,7 +76,7 @@ public final class AntPathRequestMatcher
} }
/** /**
* Creates a matcher with the supplied pattern and HTTP method in a case insensitive * Creates a matcher with the supplied pattern and HTTP method in a case sensitive
* manner. * manner.
* *
* @param pattern the ant pattern to use for matching * @param pattern the ant pattern to use for matching
@@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
/** /**
* @author Rob Winch * @author Rob Winch
* @author Eddú Meléndez
*/ */
public class StrictHttpFirewallTests { public class StrictHttpFirewallTests {
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.", public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.",
@@ -428,4 +429,20 @@ public class StrictHttpFirewallTests {
this.firewall.getFirewalledRequest(request); this.firewall.getFirewalledRequest(request);
} }
@Test
public void getFirewalledRequestWhenTrustedDomainThenNoException() {
this.request.addHeader("Host", "example.org");
this.firewall.setAllowedHostnames(hostname -> hostname.equals("example.org"));
assertThatCode(() -> this.firewall.getFirewalledRequest(this.request)).doesNotThrowAnyException();
}
@Test(expected = RequestRejectedException.class)
public void getFirewalledRequestWhenUntrustedDomainThenException() {
this.request.addHeader("Host", "example.org");
this.firewall.setAllowedHostnames(hostname -> hostname.equals("myexample.org"));
this.firewall.getFirewalledRequest(this.request);
}
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,10 +20,14 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher.MatchResult;
import org.springframework.web.server.WebFilterChain; import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.WebSession; import org.springframework.web.server.WebSession;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@@ -33,9 +37,11 @@ import reactor.test.publisher.PublisherProbe;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static org.springframework.mock.web.server.MockServerWebExchange.from;
/** /**
* @author Rob Winch * @author Rob Winch
* @author Parikshit Dutta
* @since 5.0 * @since 5.0
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
@@ -49,10 +55,10 @@ public class CsrfWebFilterTests {
private CsrfWebFilter csrfFilter = new CsrfWebFilter(); private CsrfWebFilter csrfFilter = new CsrfWebFilter();
private MockServerWebExchange get = MockServerWebExchange.from( private MockServerWebExchange get = from(
MockServerHttpRequest.get("/")); MockServerHttpRequest.get("/"));
private MockServerWebExchange post = MockServerWebExchange.from( private MockServerWebExchange post = from(
MockServerHttpRequest.post("/")); MockServerHttpRequest.post("/"));
@Test @Test
@@ -104,7 +110,7 @@ public class CsrfWebFilterTests {
this.csrfFilter.setCsrfTokenRepository(this.repository); this.csrfFilter.setCsrfTokenRepository(this.repository);
when(this.repository.loadToken(any())) when(this.repository.loadToken(any()))
.thenReturn(Mono.just(this.token)); .thenReturn(Mono.just(this.token));
this.post = MockServerWebExchange.from(MockServerHttpRequest.post("/") this.post = from(MockServerHttpRequest.post("/")
.body(this.token.getParameterName() + "="+this.token.getToken()+"INVALID")); .body(this.token.getParameterName() + "="+this.token.getToken()+"INVALID"));
Mono<Void> result = this.csrfFilter.filter(this.post, this.chain); Mono<Void> result = this.csrfFilter.filter(this.post, this.chain);
@@ -125,7 +131,7 @@ public class CsrfWebFilterTests {
.thenReturn(Mono.just(this.token)); .thenReturn(Mono.just(this.token));
when(this.repository.generateToken(any())) when(this.repository.generateToken(any()))
.thenReturn(Mono.just(this.token)); .thenReturn(Mono.just(this.token));
this.post = MockServerWebExchange.from(MockServerHttpRequest.post("/") this.post = from(MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_FORM_URLENCODED) .contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(this.token.getParameterName() + "="+this.token.getToken())); .body(this.token.getParameterName() + "="+this.token.getToken()));
@@ -142,7 +148,7 @@ public class CsrfWebFilterTests {
this.csrfFilter.setCsrfTokenRepository(this.repository); this.csrfFilter.setCsrfTokenRepository(this.repository);
when(this.repository.loadToken(any())) when(this.repository.loadToken(any()))
.thenReturn(Mono.just(this.token)); .thenReturn(Mono.just(this.token));
this.post = MockServerWebExchange.from(MockServerHttpRequest.post("/") this.post = from(MockServerHttpRequest.post("/")
.header(this.token.getHeaderName(), this.token.getToken()+"INVALID")); .header(this.token.getHeaderName(), this.token.getToken()+"INVALID"));
Mono<Void> result = this.csrfFilter.filter(this.post, this.chain); Mono<Void> result = this.csrfFilter.filter(this.post, this.chain);
@@ -163,7 +169,7 @@ public class CsrfWebFilterTests {
.thenReturn(Mono.just(this.token)); .thenReturn(Mono.just(this.token));
when(this.repository.generateToken(any())) when(this.repository.generateToken(any()))
.thenReturn(Mono.just(this.token)); .thenReturn(Mono.just(this.token));
this.post = MockServerWebExchange.from(MockServerHttpRequest.post("/") this.post = from(MockServerHttpRequest.post("/")
.header(this.token.getHeaderName(), this.token.getToken())); .header(this.token.getHeaderName(), this.token.getToken()));
Mono<Void> result = this.csrfFilter.filter(this.post, this.chain); Mono<Void> result = this.csrfFilter.filter(this.post, this.chain);
@@ -173,4 +179,14 @@ public class CsrfWebFilterTests {
chainResult.assertWasSubscribed(); chainResult.assertWasSubscribed();
} }
@Test
// gh-8452
public void matchesRequireCsrfProtectionWhenNonStandardHTTPMethodIsUsed() {
HttpMethod customHttpMethod = HttpMethod.resolve("non-standard-http-method");
MockServerWebExchange nonStandardHttpRequest = from(MockServerHttpRequest.method(customHttpMethod, "/"));
ServerWebExchangeMatcher serverWebExchangeMatcher = CsrfWebFilter.DEFAULT_CSRF_MATCHER;
assertThat(serverWebExchangeMatcher.matches(nonStandardHttpRequest).map(MatchResult::isMatch).block()).isTrue();
}
} }