Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37568780a1 | |||
| d80b1865a5 | |||
| 52c80c78e5 | |||
| ded83cc1b3 | |||
| 7a1833c1df | |||
| e6630ea0f1 | |||
| 2400e8fde2 | |||
| f05d70a4a5 | |||
| 8bb4e72aff | |||
| f58a262eb4 | |||
| c0154f2315 | |||
| cea2b556d6 | |||
| faa02e8bc0 | |||
| d9f57492d4 | |||
| b007fdc333 |
+3
-4
@@ -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
|
||||||
// ==================================================================================================
|
// ==================================================================================================
|
||||||
|
|
||||||
|
|||||||
-2
@@ -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;
|
||||||
|
|||||||
+2
-1
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-5
@@ -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());
|
||||||
|
|||||||
+2
-2
@@ -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
|
||||||
|
|||||||
+18
-1
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-7
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user