Skip to content

Commit 6db7b45

Browse files
committed
DelegatingServerLogoutHandler Executes Sequentially
Fixes gh-7723
1 parent 840d3aa commit 6db7b45

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

web/src/main/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandler.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Collection;
2222
import java.util.List;
2323

24+
import reactor.core.publisher.Flux;
2425
import reactor.core.publisher.Mono;
2526

2627
import org.springframework.security.core.Authentication;
@@ -48,12 +49,8 @@ public DelegatingServerLogoutHandler(Collection<ServerLogoutHandler> delegates)
4849

4950
@Override
5051
public Mono<Void> logout(WebFilterExchange exchange, Authentication authentication) {
51-
List<Mono<Void>> results = new ArrayList<>();
52-
for (ServerLogoutHandler delegate : delegates) {
53-
if (delegate != null) {
54-
results.add(delegate.logout(exchange, authentication));
55-
}
56-
}
57-
return Mono.when(results);
52+
return Flux.fromIterable(this.delegates)
53+
.concatMap(delegate -> delegate.logout(exchange, authentication))
54+
.then();
5855
}
5956
}

web/src/test/java/org/springframework/security/web/server/authentication/logout/DelegatingServerLogoutHandlerTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.security.web.server.authentication.logout;
1818

19+
import static org.assertj.core.api.Assertions.assertThat;
1920
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2021
import static org.mockito.Mockito.*;
2122

@@ -28,9 +29,14 @@
2829
import org.springframework.security.core.Authentication;
2930
import org.springframework.security.web.server.WebFilterExchange;
3031

32+
import reactor.core.publisher.Mono;
3133
import reactor.test.publisher.PublisherProbe;
3234

35+
import java.time.Duration;
3336
import java.util.List;
37+
import java.util.concurrent.CountDownLatch;
38+
import java.util.concurrent.TimeUnit;
39+
import java.util.concurrent.atomic.AtomicBoolean;
3440

3541
/**
3642
* @author Eric Deandrea
@@ -98,4 +104,26 @@ public void logoutWhenMultipleThenExecuted() {
98104
this.delegate1Result.assertWasSubscribed();
99105
this.delegate2Result.assertWasSubscribed();
100106
}
107+
108+
@Test
109+
public void logoutSequential() throws Exception {
110+
AtomicBoolean slowDone = new AtomicBoolean();
111+
CountDownLatch latch = new CountDownLatch(1);
112+
ServerLogoutHandler slow = (exchange, authentication) ->
113+
Mono.delay(Duration.ofMillis(100))
114+
.doOnSuccess(__ -> slowDone.set(true))
115+
.then();
116+
ServerLogoutHandler second = (exchange, authentication) ->
117+
Mono.fromRunnable(() -> {
118+
latch.countDown();
119+
assertThat(slowDone.get())
120+
.describedAs("ServerLogoutHandler should be executed sequentially")
121+
.isTrue();
122+
});
123+
DelegatingServerLogoutHandler handler = new DelegatingServerLogoutHandler(slow, second);
124+
125+
handler.logout(this.exchange, this.authentication).block();
126+
127+
assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
128+
}
101129
}

0 commit comments

Comments
 (0)