Browse Source

Cache Mono that generate the CSRF token

Closes gh-9113
pull/9878/head
Tomoki Tsubaki 5 years ago committed by Josh Cummings
parent
commit
0c8b6df82a
No known key found for this signature in database
GPG Key ID: 49EF60DD7FF83443
  1. 2
      web/src/main/java/org/springframework/security/web/server/csrf/CsrfWebFilter.java
  2. 23
      web/src/test/java/org/springframework/security/web/server/csrf/CsrfWebFilterTests.java

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

@ -191,7 +191,7 @@ public class CsrfWebFilter implements WebFilter { @@ -191,7 +191,7 @@ public class CsrfWebFilter implements WebFilter {
private Mono<CsrfToken> generateToken(ServerWebExchange exchange) {
return this.csrfTokenRepository.generateToken(exchange)
.delayUntil((token) -> this.csrfTokenRepository.saveToken(exchange, token));
.delayUntil((token) -> this.csrfTokenRepository.saveToken(exchange, token)).cache();
}
private static class DefaultRequireCsrfProtectionMatcher implements ServerWebExchangeMatcher {

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

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package org.springframework.security.web.server.csrf;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -227,6 +230,26 @@ public class CsrfWebFilterTests { @@ -227,6 +230,26 @@ public class CsrfWebFilterTests {
.isForbidden();
}
// gh-9113
@Test
public void filterWhenSubscribingCsrfTokenMultipleTimesThenGenerateOnlyOnce() {
this.csrfFilter.setCsrfTokenRepository(this.repository);
given(this.repository.loadToken(any())).willReturn(Mono.empty());
AtomicInteger count = new AtomicInteger();
given(this.repository.generateToken(any())).willReturn(Mono.fromCallable(() -> {
count.incrementAndGet();
return this.token;
}));
given(this.repository.saveToken(any(), any())).willReturn(Mono.empty());
AtomicReference<Mono<CsrfToken>> tokenFromExchange = new AtomicReference<>();
given(this.chain.filter(any())).willReturn(
Mono.fromRunnable(() -> tokenFromExchange.set(this.get.getAttribute(CsrfToken.class.getName()))));
this.csrfFilter.filter(this.get, this.chain).block();
tokenFromExchange.get().block();
tokenFromExchange.get().block();
assertThat(count).hasValue(1);
}
@RestController
static class OkController {

Loading…
Cancel
Save