|
|
|
|
@ -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 { |
|
|
|
|
|
|
|
|
|
|