DelegatingServerAuthenticationSuccessHandler Executes Sequentially
Fixes gh-7728
This commit is contained in:
parent
6db7b457b7
commit
bd6ff1f319
|
@ -19,11 +19,11 @@ package org.springframework.security.web.server.authentication;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.web.server.WebFilterExchange;
|
import org.springframework.security.web.server.WebFilterExchange;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegates to a collection of {@link ServerAuthenticationSuccessHandler} implementations.
|
* Delegates to a collection of {@link ServerAuthenticationSuccessHandler} implementations.
|
||||||
|
@ -42,10 +42,8 @@ public class DelegatingServerAuthenticationSuccessHandler implements ServerAuthe
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> onAuthenticationSuccess(WebFilterExchange exchange,
|
public Mono<Void> onAuthenticationSuccess(WebFilterExchange exchange,
|
||||||
Authentication authentication) {
|
Authentication authentication) {
|
||||||
List<Mono<Void>> results = new ArrayList<>();
|
return Flux.fromIterable(this.delegates)
|
||||||
for (ServerAuthenticationSuccessHandler delegate : delegates) {
|
.concatMap(delegate -> delegate.onAuthenticationSuccess(exchange, authentication))
|
||||||
results.add(delegate.onAuthenticationSuccess(exchange, authentication));
|
.then();
|
||||||
}
|
|
||||||
return Mono.when(results);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.security.web.server.authentication;
|
package org.springframework.security.web.server.authentication;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -27,9 +23,19 @@ import org.mockito.Mock;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.web.server.WebFilterExchange;
|
import org.springframework.security.web.server.WebFilterExchange;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.test.publisher.PublisherProbe;
|
import reactor.test.publisher.PublisherProbe;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
|
@ -88,4 +94,26 @@ public class DelegatingServerAuthenticationSuccessHandlerTests {
|
||||||
this.delegate1Result.assertWasSubscribed();
|
this.delegate1Result.assertWasSubscribed();
|
||||||
this.delegate2Result.assertWasSubscribed();
|
this.delegate2Result.assertWasSubscribed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onAuthenticationSuccessSequential() throws Exception {
|
||||||
|
AtomicBoolean slowDone = new AtomicBoolean();
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
ServerAuthenticationSuccessHandler slow = (exchange, authentication) ->
|
||||||
|
Mono.delay(Duration.ofMillis(100))
|
||||||
|
.doOnSuccess(__ -> slowDone.set(true))
|
||||||
|
.then();
|
||||||
|
ServerAuthenticationSuccessHandler second = (exchange, authentication) ->
|
||||||
|
Mono.fromRunnable(() -> {
|
||||||
|
latch.countDown();
|
||||||
|
assertThat(slowDone.get())
|
||||||
|
.describedAs("ServerAuthenticationSuccessHandler should be executed sequentially")
|
||||||
|
.isTrue();
|
||||||
|
});
|
||||||
|
DelegatingServerAuthenticationSuccessHandler handler = new DelegatingServerAuthenticationSuccessHandler(slow, second);
|
||||||
|
|
||||||
|
handler.onAuthenticationSuccess(this.exchange, this.authentication).block();
|
||||||
|
|
||||||
|
assertThat(latch.await(3, TimeUnit.SECONDS)).isTrue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue