2 changed files with 135 additions and 0 deletions
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
/* |
||||
* Copyright 2002-2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.security.core.Authentication; |
||||
import org.springframework.util.Assert; |
||||
|
||||
import reactor.core.publisher.Flux; |
||||
import reactor.core.publisher.Mono; |
||||
|
||||
/** |
||||
* A {@link ReactiveAuthenticationManager} that delegates to other {@link ReactiveAuthenticationManager} instances using |
||||
* the result from the first non empty result. |
||||
* |
||||
* @author Rob Winch |
||||
* @since 5.1 |
||||
*/ |
||||
public class DelegatingReactiveAuthenticationManager |
||||
implements ReactiveAuthenticationManager { |
||||
private final List<ReactiveAuthenticationManager> delegates; |
||||
|
||||
public DelegatingReactiveAuthenticationManager( |
||||
ReactiveAuthenticationManager... entryPoints) { |
||||
this(Arrays.asList(entryPoints)); |
||||
} |
||||
|
||||
public DelegatingReactiveAuthenticationManager( |
||||
List<ReactiveAuthenticationManager> entryPoints) { |
||||
Assert.notEmpty(entryPoints, "entryPoints cannot be null"); |
||||
this.delegates = entryPoints; |
||||
} |
||||
|
||||
public Mono<Authentication> authenticate(Authentication authentication) { |
||||
return Flux.fromIterable(this.delegates) |
||||
.concatMap(m -> m.authenticate(authentication)) |
||||
.next(); |
||||
} |
||||
} |
||||
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
/* |
||||
* Copyright 2002-2018 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.security.authentication; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.Mock; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
import org.springframework.security.core.Authentication; |
||||
import reactor.core.publisher.Mono; |
||||
import reactor.test.StepVerifier; |
||||
|
||||
import java.time.Duration; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.ArgumentMatchers.any; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
/** |
||||
* @author Rob Winch |
||||
* @since 5.1 |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class DelegatingReactiveAuthenticationManagerTests { |
||||
@Mock |
||||
ReactiveAuthenticationManager delegate1; |
||||
|
||||
@Mock |
||||
ReactiveAuthenticationManager delegate2; |
||||
|
||||
@Mock |
||||
Authentication authentication; |
||||
|
||||
@Test |
||||
public void authenticateWhenEmptyAndNotThenReturnsNotEmpty() { |
||||
when(this.delegate1.authenticate(any())).thenReturn(Mono.empty()); |
||||
when(this.delegate2.authenticate(any())).thenReturn(Mono.just(this.authentication)); |
||||
|
||||
DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, this.delegate2); |
||||
|
||||
assertThat(manager.authenticate(this.authentication).block()).isEqualTo(this.authentication); |
||||
} |
||||
|
||||
@Test |
||||
public void authenticateWhenNotEmptyThenOtherDelegatesNotSubscribed() { |
||||
// delay to try and force delegate2 to finish (i.e. make sure we didn't use flatMap)
|
||||
when(this.delegate1.authenticate(any())).thenReturn(Mono.just(this.authentication).delayElement(Duration.ofMillis(100))); |
||||
|
||||
DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, this.delegate2); |
||||
|
||||
StepVerifier.create(manager.authenticate(this.authentication)) |
||||
.expectNext(this.authentication) |
||||
.verifyComplete(); |
||||
} |
||||
|
||||
@Test |
||||
public void authenticateWhenBadCredentialsThenDelegate2NotInvokedAndError() { |
||||
when(this.delegate1.authenticate(any())).thenReturn(Mono.error(new BadCredentialsException("Test"))); |
||||
|
||||
DelegatingReactiveAuthenticationManager manager = new DelegatingReactiveAuthenticationManager(this.delegate1, this.delegate2); |
||||
|
||||
StepVerifier.create(manager.authenticate(this.authentication)) |
||||
.expectError(BadCredentialsException.class) |
||||
.verify(); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue